goat3d

changeset 27:4deb0b12fe14

wtf... corrupted heap?
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 29 Sep 2013 08:20:19 +0300
parents 1c601bf07b86
children 9ba3e2fb8a33
files exporters/maxgoat/maxgoat.vcxproj exporters/maxgoat/maxgoat.vcxproj.filters exporters/maxgoat/src/maxgoat.cc goat3d.vcxproj goat3d.vcxproj.filters libs/anim/anim.c libs/anim/anim.h libs/anim/config.h libs/anim/dynarr.c libs/anim/dynarr.h libs/anim/track.c libs/anim/track.h libs/vmath/basis.cc libs/vmath/basis.h libs/vmath/basis_c.c libs/vmath/geom.c libs/vmath/geom.h libs/vmath/matrix.cc libs/vmath/matrix.h libs/vmath/matrix.inl libs/vmath/matrix_c.c libs/vmath/quat.cc libs/vmath/quat.h libs/vmath/quat.inl libs/vmath/quat_c.c libs/vmath/ray.cc libs/vmath/ray.h libs/vmath/ray.inl libs/vmath/ray_c.c libs/vmath/sphvec.cc libs/vmath/sphvec.h libs/vmath/vector.cc libs/vmath/vector.h libs/vmath/vector.inl libs/vmath/vmath.c libs/vmath/vmath.h libs/vmath/vmath.inl libs/vmath/vmath_config.h libs/vmath/vmath_types.h src/goat3d.cc src/goat3d.h
diffstat 41 files changed, 6217 insertions(+), 52 deletions(-) [+]
line diff
     1.1 --- a/exporters/maxgoat/maxgoat.vcxproj	Sat Sep 28 20:36:55 2013 +0300
     1.2 +++ b/exporters/maxgoat/maxgoat.vcxproj	Sun Sep 29 08:20:19 2013 +0300
     1.3 @@ -33,7 +33,7 @@
     1.4    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
     1.5      <ConfigurationType>DynamicLibrary</ConfigurationType>
     1.6      <UseDebugLibraries>true</UseDebugLibraries>
     1.7 -    <PlatformToolset>v110</PlatformToolset>
     1.8 +    <PlatformToolset>v100</PlatformToolset>
     1.9      <CharacterSet>Unicode</CharacterSet>
    1.10    </PropertyGroup>
    1.11    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    1.12 @@ -46,7 +46,7 @@
    1.13    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    1.14      <ConfigurationType>DynamicLibrary</ConfigurationType>
    1.15      <UseDebugLibraries>false</UseDebugLibraries>
    1.16 -    <PlatformToolset>v110</PlatformToolset>
    1.17 +    <PlatformToolset>v100</PlatformToolset>
    1.18      <WholeProgramOptimization>true</WholeProgramOptimization>
    1.19      <CharacterSet>Unicode</CharacterSet>
    1.20    </PropertyGroup>
    1.21 @@ -70,7 +70,7 @@
    1.22      <LinkIncremental>true</LinkIncremental>
    1.23    </PropertyGroup>
    1.24    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    1.25 -    <LinkIncremental>true</LinkIncremental>
    1.26 +    <LinkIncremental>false</LinkIncremental>
    1.27    </PropertyGroup>
    1.28    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    1.29      <LinkIncremental>false</LinkIncremental>
    1.30 @@ -98,14 +98,14 @@
    1.31        </PrecompiledHeader>
    1.32        <WarningLevel>Level3</WarningLevel>
    1.33        <Optimization>Disabled</Optimization>
    1.34 -      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MAXGOAT_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    1.35 -      <DisableSpecificWarnings>4996</DisableSpecificWarnings>
    1.36 +      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MAXGOAT_EXPORTS;%(PreprocessorDefinitions);BUILD_MAXPLUGIN</PreprocessorDefinitions>
    1.37 +      <DisableSpecificWarnings>4996;4244</DisableSpecificWarnings>
    1.38        <AdditionalIncludeDirectories>$(SolutionDir)\src</AdditionalIncludeDirectories>
    1.39      </ClCompile>
    1.40      <Link>
    1.41        <SubSystem>Windows</SubSystem>
    1.42        <GenerateDebugInformation>true</GenerateDebugInformation>
    1.43 -      <AdditionalDependencies>goat3d-x64.lib;libvmath-x64.lib;libanim-x64.lib;%(AdditionalDependencies)</AdditionalDependencies>
    1.44 +      <AdditionalDependencies>goat3d-x64.lib;%(AdditionalDependencies)</AdditionalDependencies>
    1.45        <AdditionalLibraryDirectories>$(TargetDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
    1.46      </Link>
    1.47      <PostBuildEvent>
    1.48 @@ -139,7 +139,7 @@
    1.49        <FunctionLevelLinking>true</FunctionLevelLinking>
    1.50        <IntrinsicFunctions>true</IntrinsicFunctions>
    1.51        <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;MAXGOAT_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    1.52 -      <DisableSpecificWarnings>4996</DisableSpecificWarnings>
    1.53 +      <DisableSpecificWarnings>4996;4244</DisableSpecificWarnings>
    1.54        <AdditionalIncludeDirectories>$(SolutionDir)\src</AdditionalIncludeDirectories>
    1.55      </ClCompile>
    1.56      <Link>
    1.57 @@ -147,7 +147,7 @@
    1.58        <GenerateDebugInformation>true</GenerateDebugInformation>
    1.59        <EnableCOMDATFolding>true</EnableCOMDATFolding>
    1.60        <OptimizeReferences>true</OptimizeReferences>
    1.61 -      <AdditionalDependencies>goat3d-x64.lib;libvmath-x64.lib;libanim-x64.lib;%(AdditionalDependencies)</AdditionalDependencies>
    1.62 +      <AdditionalDependencies>goat3d-x64.lib;%(AdditionalDependencies)</AdditionalDependencies>
    1.63        <AdditionalLibraryDirectories>$(TargetDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
    1.64      </Link>
    1.65      <PostBuildEvent>
    1.66 @@ -157,9 +157,6 @@
    1.67    <ItemGroup>
    1.68      <ClCompile Include="src\maxgoat.cc" />
    1.69    </ItemGroup>
    1.70 -  <ItemGroup>
    1.71 -    <ClInclude Include="src\config.h" />
    1.72 -  </ItemGroup>
    1.73    <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
    1.74    <ImportGroup Label="ExtensionTargets">
    1.75    </ImportGroup>
     2.1 --- a/exporters/maxgoat/maxgoat.vcxproj.filters	Sat Sep 28 20:36:55 2013 +0300
     2.2 +++ b/exporters/maxgoat/maxgoat.vcxproj.filters	Sun Sep 29 08:20:19 2013 +0300
     2.3 @@ -11,9 +11,4 @@
     2.4        <Filter>src</Filter>
     2.5      </ClCompile>
     2.6    </ItemGroup>
     2.7 -  <ItemGroup>
     2.8 -    <ClInclude Include="src\config.h">
     2.9 -      <Filter>src</Filter>
    2.10 -    </ClInclude>
    2.11 -  </ItemGroup>
    2.12  </Project>
    2.13 \ No newline at end of file
     3.1 --- a/exporters/maxgoat/src/maxgoat.cc	Sat Sep 28 20:36:55 2013 +0300
     3.2 +++ b/exporters/maxgoat/src/maxgoat.cc	Sun Sep 29 08:20:19 2013 +0300
     3.3 @@ -1,6 +1,8 @@
     3.4  #include <stdio.h>
     3.5  #include <string.h>
     3.6 +#include <stdlib.h>
     3.7  #include <errno.h>
     3.8 +#include <map>
     3.9  #include <windows.h>
    3.10  #include <shlobj.h>
    3.11  #include "max.h"
    3.12 @@ -33,6 +35,10 @@
    3.13  static HINSTANCE hinst;
    3.14  
    3.15  class GoatExporter : public SceneExport {
    3.16 +private:
    3.17 +	//std::map<IGameMaterial*, goat3d_material*> mtlmap;
    3.18 +	//std::map<IGameNode*, goat3d_node*> nodemap;
    3.19 +
    3.20  public:
    3.21  	IGameScene *igame;
    3.22  
    3.23 @@ -49,9 +55,13 @@
    3.24  
    3.25  	int DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface, BOOL silent = FALSE, DWORD opt = 0);
    3.26  
    3.27 -	void export_materials(goat3d *goat);
    3.28 -	void export_meshes(goat3d *goat);
    3.29 -	void process_node(goat3d *goat, IGameNode *maxnode);
    3.30 +	void process_materials(goat3d *goat);
    3.31 +
    3.32 +	void process_node(goat3d *goat, goat3d_node *parent, IGameNode *maxnode);
    3.33 +
    3.34 +	void process_mesh(goat3d *goat, goat3d_mesh *mesh, IGameObject *maxobj);
    3.35 +	void process_light(goat3d *goat, goat3d_light *light, IGameObject *maxobj);
    3.36 +	void process_camera(goat3d *goat, goat3d_camera *cam, IGameObject *maxobj);
    3.37  };
    3.38  
    3.39  
    3.40 @@ -62,7 +72,7 @@
    3.41  
    3.42  const TCHAR *GoatExporter::Ext(int n)
    3.43  {
    3.44 -	return L"txt";
    3.45 +	return L"xml";
    3.46  }
    3.47  
    3.48  const TCHAR *GoatExporter::LongDesc()
    3.49 @@ -108,6 +118,9 @@
    3.50  int GoatExporter::DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface,
    3.51  		BOOL non_interactive, DWORD opt)
    3.52  {
    3.53 +	//mtlmap.clear();
    3.54 +	//nodemap.clear();
    3.55 +
    3.56  	char fname[512];
    3.57  	wcstombs(fname, name, sizeof fname - 1);
    3.58  
    3.59 @@ -122,20 +135,19 @@
    3.60  
    3.61  	goat3d *goat = goat3d_create();
    3.62  
    3.63 -	export_materials(goat);
    3.64 -	export_meshes(goat);
    3.65 +	process_materials(goat);
    3.66 +
    3.67 +	// process all nodes
    3.68 +	for(int i=0; i<igame->GetTopLevelNodeCount(); i++) {
    3.69 +		IGameNode *node = igame->GetTopLevelNode(i);
    3.70 +		process_node(goat, 0, node);
    3.71 +	}
    3.72  
    3.73  	if(goat3d_save(goat, fname) == -1) {
    3.74  		goat3d_free(goat);
    3.75  		return IMPEXP_FAIL;
    3.76  	}
    3.77  
    3.78 -	// process all nodes
    3.79 -	for(int i=0; i<igame->GetTopLevelNodeCount(); i++) {
    3.80 -		IGameNode *node = igame->GetTopLevelNode(i);
    3.81 -		process_node(goat, node);
    3.82 -	}
    3.83 -
    3.84  	goat3d_free(goat);
    3.85  	return IMPEXP_SUCCESS;
    3.86  }
    3.87 @@ -148,7 +160,7 @@
    3.88  	return str;
    3.89  }
    3.90  
    3.91 -void GoatExporter::export_materials(goat3d *goat)
    3.92 +void GoatExporter::process_materials(goat3d *goat)
    3.93  {
    3.94  	IGameProperty *prop;
    3.95  
    3.96 @@ -231,19 +243,138 @@
    3.97  			}
    3.98  
    3.99  			goat3d_add_mtl(goat, mtl);
   3.100 +			//mtlmap[maxmtl] = mtl;
   3.101  		}
   3.102  	}
   3.103  }
   3.104  
   3.105 -void GoatExporter::export_meshes(goat3d *goat)
   3.106 +void GoatExporter::process_node(goat3d *goat, goat3d_node *parent, IGameNode *maxnode)
   3.107  {
   3.108 -	Tab<IGameNode*> meshes = igame->GetIGameNodeByType(IGameObject::IGAME_MESH);
   3.109 +	goat3d_node *node = goat3d_create_node();
   3.110 +	goat3d_add_node(goat, node);
   3.111  
   3.112 -	for(int i=0; i<meshes.Count(); i++) {
   3.113 -		const char *name = max_string(meshes[i]->GetName());
   3.114 +	const char *name = max_string(maxnode->GetName());
   3.115 +	if(name) {
   3.116 +		goat3d_set_node_name(node, name);
   3.117 +	}
   3.118 +
   3.119 +	// no animation yet, just get the static PRS
   3.120 +	GMatrix maxmatrix = maxnode->GetObjectTM();
   3.121 +	Point3 trans = maxmatrix.Translation();
   3.122 +	Quat rot = maxmatrix.Rotation();
   3.123 +	Point3 scale = maxmatrix.Scaling();
   3.124 +
   3.125 +	goat3d_set_node_position(node, trans.x, trans.y, trans.z, 0);
   3.126 +	goat3d_set_node_rotation(node, rot.x, rot.y, rot.z, rot.w, 0);
   3.127 +	goat3d_set_node_scaling(node, scale.x, scale.y, scale.z, 0);
   3.128 +
   3.129 +	IGameObject *maxobj = maxnode->GetIGameObject();
   3.130 +	IGameObject::ObjectTypes type = maxobj->GetIGameType();
   3.131 +
   3.132 +	switch(type) {
   3.133 +	case IGameObject::IGAME_MESH:
   3.134 +		{
   3.135 +			goat3d_mesh *mesh = goat3d_create_mesh();
   3.136 +			if(name) goat3d_set_mesh_name(mesh, name);
   3.137 +			goat3d_set_node_object(node, GOAT3D_NODE_MESH, mesh);
   3.138 +
   3.139 +			// get the node material and assign it to the mesh
   3.140 +			IGameMaterial *maxmtl = maxnode->GetNodeMaterial();
   3.141 +			goat3d_material *mtl = 0;//mtlmap[maxmtl];
   3.142 +			if(mtl) {
   3.143 +				goat3d_set_mesh_mtl(mesh, mtl);
   3.144 +			}
   3.145 +
   3.146 +			process_mesh(goat, mesh, maxobj);
   3.147 +		}
   3.148 +		break;
   3.149 +
   3.150 +	case IGameObject::IGAME_LIGHT:
   3.151 +		{
   3.152 +			goat3d_light *light = goat3d_create_light();
   3.153 +			//if(name) goat3d_set_light_name(light, name);
   3.154 +			goat3d_set_node_object(node, GOAT3D_NODE_LIGHT, light);
   3.155 +
   3.156 +			process_light(goat, light, maxobj);
   3.157 +		}
   3.158 +		break;
   3.159 +
   3.160 +	case IGameObject::IGAME_CAMERA:
   3.161 +		{
   3.162 +			goat3d_camera *cam = goat3d_create_camera();
   3.163 +			//if(name) goat3d_set_camera_name(camera, name);
   3.164 +			goat3d_set_node_object(node, GOAT3D_NODE_CAMERA, cam);
   3.165 +
   3.166 +			process_camera(goat, cam, maxobj);
   3.167 +		}
   3.168 +		break;
   3.169 +
   3.170 +	default:
   3.171 +		// otherwise don't assign an object, essentially treating it as a null node
   3.172 +		break;
   3.173 +	}
   3.174 +		
   3.175 +
   3.176 +	for(int i=0; i<maxnode->GetChildCount(); i++) {
   3.177 +		process_node(goat, node, maxnode->GetNodeChild(i));
   3.178  	}
   3.179  }
   3.180  
   3.181 +void GoatExporter::process_mesh(goat3d *goat, goat3d_mesh *mesh, IGameObject *maxobj)
   3.182 +{
   3.183 +	IGameMesh *maxmesh = (IGameMesh*)maxobj;
   3.184 +
   3.185 +	maxmesh->SetCreateOptimizedNormalList();	// not needed any more according to docs
   3.186 +	maxobj->InitializeData();
   3.187 +
   3.188 +	int num_verts = maxmesh->GetNumberOfVerts();
   3.189 +	assert(maxmesh->GetNumberOfTexVerts() == num_verts);
   3.190 +
   3.191 +	float *vertices = new float[num_verts * 3];
   3.192 +	float *normals = new float[num_verts * 3];
   3.193 +	float *texcoords = new float[num_verts * 2];
   3.194 +
   3.195 +	for(int i=0; i<num_verts; i++) {
   3.196 +		Point3 v = maxmesh->GetVertex(i, true);
   3.197 +		vertices[i * 3] = v.x;
   3.198 +		vertices[i * 3 + 1] = v.y;
   3.199 +		vertices[i * 3 + 2] = v.z;
   3.200 +	}
   3.201 +
   3.202 +	for(int i=0; i<maxmesh->GetNumberOfNormals(); i++) {
   3.203 +		Point3 norm = maxmesh->GetNormal(i);
   3.204 +
   3.205 +		int vidx = maxmesh->GetNormalVertexIndex(i);
   3.206 +		normals[vidx * 3] = norm.x;
   3.207 +		normals[vidx * 3 + 1] = norm.y;
   3.208 +		normals[vidx * 3 + 2] = norm.z;
   3.209 +	}
   3.210 +
   3.211 +	for(int i=0; i<maxmesh->GetNumberOfTexVerts(); i++) {
   3.212 +		Point3 tex = maxmesh->GetTexVertex(i);
   3.213 +
   3.214 +		texcoords[i * 2] = tex.x;
   3.215 +		texcoords[i * 2 + 1] = tex.y;
   3.216 +	}
   3.217 +
   3.218 +	goat3d_set_mesh_attribs(mesh, GOAT3D_MESH_ATTR_VERTEX, vertices, num_verts);
   3.219 +	goat3d_set_mesh_attribs(mesh, GOAT3D_MESH_ATTR_NORMAL, normals, num_verts);
   3.220 +	goat3d_set_mesh_attribs(mesh, GOAT3D_MESH_ATTR_TEXCOORD, texcoords, num_verts);
   3.221 +
   3.222 +	delete [] vertices;
   3.223 +	delete [] normals;
   3.224 +	delete [] texcoords;
   3.225 +}
   3.226 +
   3.227 +void GoatExporter::process_light(goat3d *goat, goat3d_light *light, IGameObject *maxobj)
   3.228 +{
   3.229 +}
   3.230 +
   3.231 +void GoatExporter::process_camera(goat3d *goat, goat3d_camera *cam, IGameObject *maxobj)
   3.232 +{
   3.233 +}
   3.234 +
   3.235 +
   3.236  // ------------------------------------------
   3.237  
   3.238  class GoatClassDesc : public ClassDesc2 {
     4.1 --- a/goat3d.vcxproj	Sat Sep 28 20:36:55 2013 +0300
     4.2 +++ b/goat3d.vcxproj	Sun Sep 29 08:20:19 2013 +0300
     4.3 @@ -19,6 +19,9 @@
     4.4      </ProjectConfiguration>
     4.5    </ItemGroup>
     4.6    <ItemGroup>
     4.7 +    <ClInclude Include="libs\anim\anim.h" />
     4.8 +    <ClInclude Include="libs\anim\dynarr.h" />
     4.9 +    <ClInclude Include="libs\anim\track.h" />
    4.10      <ClInclude Include="libs\openctm\internal.h" />
    4.11      <ClInclude Include="libs\openctm\liblzma\Alloc.h" />
    4.12      <ClInclude Include="libs\openctm\liblzma\LzFind.h" />
    4.13 @@ -31,6 +34,16 @@
    4.14      <ClInclude Include="libs\openctm\openctm.h" />
    4.15      <ClInclude Include="libs\openctm\openctmpp.h" />
    4.16      <ClInclude Include="libs\tinyxml2\tinyxml2.h" />
    4.17 +    <ClInclude Include="libs\vmath\basis.h" />
    4.18 +    <ClInclude Include="libs\vmath\geom.h" />
    4.19 +    <ClInclude Include="libs\vmath\matrix.h" />
    4.20 +    <ClInclude Include="libs\vmath\quat.h" />
    4.21 +    <ClInclude Include="libs\vmath\ray.h" />
    4.22 +    <ClInclude Include="libs\vmath\sphvec.h" />
    4.23 +    <ClInclude Include="libs\vmath\vector.h" />
    4.24 +    <ClInclude Include="libs\vmath\vmath.h" />
    4.25 +    <ClInclude Include="libs\vmath\vmath_config.h" />
    4.26 +    <ClInclude Include="libs\vmath\vmath_types.h" />
    4.27      <ClInclude Include="src\camera.h" />
    4.28      <ClInclude Include="src\chunk.h" />
    4.29      <ClInclude Include="src\goat3d.h" />
    4.30 @@ -44,6 +57,9 @@
    4.31      <ClInclude Include="src\xform_node.h" />
    4.32    </ItemGroup>
    4.33    <ItemGroup>
    4.34 +    <ClCompile Include="libs\anim\anim.c" />
    4.35 +    <ClCompile Include="libs\anim\dynarr.c" />
    4.36 +    <ClCompile Include="libs\anim\track.c" />
    4.37      <ClCompile Include="libs\openctm\compressMG1.c" />
    4.38      <ClCompile Include="libs\openctm\compressMG2.c" />
    4.39      <ClCompile Include="libs\openctm\compressRAW.c" />
    4.40 @@ -55,6 +71,18 @@
    4.41      <ClCompile Include="libs\openctm\openctm.c" />
    4.42      <ClCompile Include="libs\openctm\stream.c" />
    4.43      <ClCompile Include="libs\tinyxml2\tinyxml2.cpp" />
    4.44 +    <ClCompile Include="libs\vmath\basis.cc" />
    4.45 +    <ClCompile Include="libs\vmath\basis_c.c" />
    4.46 +    <ClCompile Include="libs\vmath\geom.c" />
    4.47 +    <ClCompile Include="libs\vmath\matrix.cc" />
    4.48 +    <ClCompile Include="libs\vmath\matrix_c.c" />
    4.49 +    <ClCompile Include="libs\vmath\quat.cc" />
    4.50 +    <ClCompile Include="libs\vmath\quat_c.c" />
    4.51 +    <ClCompile Include="libs\vmath\ray.cc" />
    4.52 +    <ClCompile Include="libs\vmath\ray_c.c" />
    4.53 +    <ClCompile Include="libs\vmath\sphvec.cc" />
    4.54 +    <ClCompile Include="libs\vmath\vector.cc" />
    4.55 +    <ClCompile Include="libs\vmath\vmath.c" />
    4.56      <ClCompile Include="src\camera.cc" />
    4.57      <ClCompile Include="src\chunk.cc" />
    4.58      <ClCompile Include="src\goat3d.cc" />
    4.59 @@ -69,6 +97,13 @@
    4.60      <ClCompile Include="src\scene.cc" />
    4.61      <ClCompile Include="src\xform_node.cc" />
    4.62    </ItemGroup>
    4.63 +  <ItemGroup>
    4.64 +    <None Include="libs\vmath\matrix.inl" />
    4.65 +    <None Include="libs\vmath\quat.inl" />
    4.66 +    <None Include="libs\vmath\ray.inl" />
    4.67 +    <None Include="libs\vmath\vector.inl" />
    4.68 +    <None Include="libs\vmath\vmath.inl" />
    4.69 +  </ItemGroup>
    4.70    <PropertyGroup Label="Globals">
    4.71      <ProjectGuid>{86BF319B-9222-4805-918D-DC1B9F77BCEF}</ProjectGuid>
    4.72      <Keyword>Win32Proj</Keyword>
    4.73 @@ -84,7 +119,7 @@
    4.74    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    4.75      <ConfigurationType>StaticLibrary</ConfigurationType>
    4.76      <UseDebugLibraries>true</UseDebugLibraries>
    4.77 -    <PlatformToolset>v110</PlatformToolset>
    4.78 +    <PlatformToolset>v100</PlatformToolset>
    4.79      <CharacterSet>Unicode</CharacterSet>
    4.80    </PropertyGroup>
    4.81    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    4.82 @@ -97,7 +132,7 @@
    4.83    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    4.84      <ConfigurationType>StaticLibrary</ConfigurationType>
    4.85      <UseDebugLibraries>false</UseDebugLibraries>
    4.86 -    <PlatformToolset>v110</PlatformToolset>
    4.87 +    <PlatformToolset>v100</PlatformToolset>
    4.88      <WholeProgramOptimization>true</WholeProgramOptimization>
    4.89      <CharacterSet>Unicode</CharacterSet>
    4.90    </PropertyGroup>
    4.91 @@ -143,14 +178,18 @@
    4.92        </PrecompiledHeader>
    4.93        <WarningLevel>Level3</WarningLevel>
    4.94        <Optimization>Disabled</Optimization>
    4.95 -      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions);OPENCTM_STATIC</PreprocessorDefinitions>
    4.96 +      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions);OPENCTM_STATIC;BUILD_MAXPLUGIN</PreprocessorDefinitions>
    4.97        <DisableSpecificWarnings>4244;4305;4996</DisableSpecificWarnings>
    4.98 -      <AdditionalIncludeDirectories>$(SolutionDir)\libs\openctm;$(SolutionDir)\libs\openctm\liblzma;$(SolutionDir)\libs\tinyxml2</AdditionalIncludeDirectories>
    4.99 +      <AdditionalIncludeDirectories>$(SolutionDir)\src;$(SolutionDir)\libs\openctm;$(SolutionDir)\libs\openctm\liblzma;$(SolutionDir)\libs\tinyxml2</AdditionalIncludeDirectories>
   4.100      </ClCompile>
   4.101      <Link>
   4.102        <SubSystem>Windows</SubSystem>
   4.103        <GenerateDebugInformation>true</GenerateDebugInformation>
   4.104      </Link>
   4.105 +    <Lib>
   4.106 +      <AdditionalDependencies>
   4.107 +      </AdditionalDependencies>
   4.108 +    </Lib>
   4.109    </ItemDefinitionGroup>
   4.110    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
   4.111      <ClCompile>
   4.112 @@ -180,7 +219,7 @@
   4.113        <IntrinsicFunctions>true</IntrinsicFunctions>
   4.114        <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions);OPENCTM_STATIC</PreprocessorDefinitions>
   4.115        <DisableSpecificWarnings>4244;4305;4996</DisableSpecificWarnings>
   4.116 -      <AdditionalIncludeDirectories>$(SolutionDir)\libs\openctm;$(SolutionDir)\libs\openctm\liblzma;$(SolutionDir)\libs\tinyxml2</AdditionalIncludeDirectories>
   4.117 +      <AdditionalIncludeDirectories>$(SolutionDir)\src;$(SolutionDir)\libs\openctm;$(SolutionDir)\libs\openctm\liblzma;$(SolutionDir)\libs\tinyxml2</AdditionalIncludeDirectories>
   4.118      </ClCompile>
   4.119      <Link>
   4.120        <SubSystem>Windows</SubSystem>
   4.121 @@ -188,6 +227,10 @@
   4.122        <EnableCOMDATFolding>true</EnableCOMDATFolding>
   4.123        <OptimizeReferences>true</OptimizeReferences>
   4.124      </Link>
   4.125 +    <Lib>
   4.126 +      <AdditionalDependencies>
   4.127 +      </AdditionalDependencies>
   4.128 +    </Lib>
   4.129    </ItemDefinitionGroup>
   4.130    <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   4.131    <ImportGroup Label="ExtensionTargets">
     5.1 --- a/goat3d.vcxproj.filters	Sat Sep 28 20:36:55 2013 +0300
     5.2 +++ b/goat3d.vcxproj.filters	Sun Sep 29 08:20:19 2013 +0300
     5.3 @@ -17,6 +17,12 @@
     5.4      <Filter Include="libs\openctm\liblzma">
     5.5        <UniqueIdentifier>{18a85bea-ddb2-49a1-a7b1-bd11b23d5549}</UniqueIdentifier>
     5.6      </Filter>
     5.7 +    <Filter Include="libs\vmath">
     5.8 +      <UniqueIdentifier>{dc4ab435-af1e-4786-8011-a7a793e229eb}</UniqueIdentifier>
     5.9 +    </Filter>
    5.10 +    <Filter Include="libs\anim">
    5.11 +      <UniqueIdentifier>{05d8010d-b4d9-4829-80ea-8c8d018e1e04}</UniqueIdentifier>
    5.12 +    </Filter>
    5.13    </ItemGroup>
    5.14    <ItemGroup>
    5.15      <ClInclude Include="src\camera.h">
    5.16 @@ -88,6 +94,45 @@
    5.17      <ClInclude Include="libs\openctm\liblzma\Types.h">
    5.18        <Filter>libs\openctm\liblzma</Filter>
    5.19      </ClInclude>
    5.20 +    <ClInclude Include="libs\anim\anim.h">
    5.21 +      <Filter>libs\anim</Filter>
    5.22 +    </ClInclude>
    5.23 +    <ClInclude Include="libs\anim\dynarr.h">
    5.24 +      <Filter>libs\anim</Filter>
    5.25 +    </ClInclude>
    5.26 +    <ClInclude Include="libs\anim\track.h">
    5.27 +      <Filter>libs\anim</Filter>
    5.28 +    </ClInclude>
    5.29 +    <ClInclude Include="libs\vmath\basis.h">
    5.30 +      <Filter>libs\vmath</Filter>
    5.31 +    </ClInclude>
    5.32 +    <ClInclude Include="libs\vmath\geom.h">
    5.33 +      <Filter>libs\vmath</Filter>
    5.34 +    </ClInclude>
    5.35 +    <ClInclude Include="libs\vmath\matrix.h">
    5.36 +      <Filter>libs\vmath</Filter>
    5.37 +    </ClInclude>
    5.38 +    <ClInclude Include="libs\vmath\quat.h">
    5.39 +      <Filter>libs\vmath</Filter>
    5.40 +    </ClInclude>
    5.41 +    <ClInclude Include="libs\vmath\ray.h">
    5.42 +      <Filter>libs\vmath</Filter>
    5.43 +    </ClInclude>
    5.44 +    <ClInclude Include="libs\vmath\sphvec.h">
    5.45 +      <Filter>libs\vmath</Filter>
    5.46 +    </ClInclude>
    5.47 +    <ClInclude Include="libs\vmath\vector.h">
    5.48 +      <Filter>libs\vmath</Filter>
    5.49 +    </ClInclude>
    5.50 +    <ClInclude Include="libs\vmath\vmath.h">
    5.51 +      <Filter>libs\vmath</Filter>
    5.52 +    </ClInclude>
    5.53 +    <ClInclude Include="libs\vmath\vmath_config.h">
    5.54 +      <Filter>libs\vmath</Filter>
    5.55 +    </ClInclude>
    5.56 +    <ClInclude Include="libs\vmath\vmath_types.h">
    5.57 +      <Filter>libs\vmath</Filter>
    5.58 +    </ClInclude>
    5.59    </ItemGroup>
    5.60    <ItemGroup>
    5.61      <ClCompile Include="src\goat3d.cc">
    5.62 @@ -162,5 +207,67 @@
    5.63      <ClCompile Include="libs\openctm\liblzma\LzmaLib.c">
    5.64        <Filter>libs\openctm\liblzma</Filter>
    5.65      </ClCompile>
    5.66 +    <ClCompile Include="libs\anim\anim.c">
    5.67 +      <Filter>libs\anim</Filter>
    5.68 +    </ClCompile>
    5.69 +    <ClCompile Include="libs\anim\dynarr.c">
    5.70 +      <Filter>libs\anim</Filter>
    5.71 +    </ClCompile>
    5.72 +    <ClCompile Include="libs\anim\track.c">
    5.73 +      <Filter>libs\anim</Filter>
    5.74 +    </ClCompile>
    5.75 +    <ClCompile Include="libs\vmath\basis.cc">
    5.76 +      <Filter>libs\vmath</Filter>
    5.77 +    </ClCompile>
    5.78 +    <ClCompile Include="libs\vmath\basis_c.c">
    5.79 +      <Filter>libs\vmath</Filter>
    5.80 +    </ClCompile>
    5.81 +    <ClCompile Include="libs\vmath\geom.c">
    5.82 +      <Filter>libs\vmath</Filter>
    5.83 +    </ClCompile>
    5.84 +    <ClCompile Include="libs\vmath\matrix.cc">
    5.85 +      <Filter>libs\vmath</Filter>
    5.86 +    </ClCompile>
    5.87 +    <ClCompile Include="libs\vmath\matrix_c.c">
    5.88 +      <Filter>libs\vmath</Filter>
    5.89 +    </ClCompile>
    5.90 +    <ClCompile Include="libs\vmath\quat.cc">
    5.91 +      <Filter>libs\vmath</Filter>
    5.92 +    </ClCompile>
    5.93 +    <ClCompile Include="libs\vmath\quat_c.c">
    5.94 +      <Filter>libs\vmath</Filter>
    5.95 +    </ClCompile>
    5.96 +    <ClCompile Include="libs\vmath\ray.cc">
    5.97 +      <Filter>libs\vmath</Filter>
    5.98 +    </ClCompile>
    5.99 +    <ClCompile Include="libs\vmath\ray_c.c">
   5.100 +      <Filter>libs\vmath</Filter>
   5.101 +    </ClCompile>
   5.102 +    <ClCompile Include="libs\vmath\sphvec.cc">
   5.103 +      <Filter>libs\vmath</Filter>
   5.104 +    </ClCompile>
   5.105 +    <ClCompile Include="libs\vmath\vector.cc">
   5.106 +      <Filter>libs\vmath</Filter>
   5.107 +    </ClCompile>
   5.108 +    <ClCompile Include="libs\vmath\vmath.c">
   5.109 +      <Filter>libs\vmath</Filter>
   5.110 +    </ClCompile>
   5.111 +  </ItemGroup>
   5.112 +  <ItemGroup>
   5.113 +    <None Include="libs\vmath\matrix.inl">
   5.114 +      <Filter>libs\vmath</Filter>
   5.115 +    </None>
   5.116 +    <None Include="libs\vmath\quat.inl">
   5.117 +      <Filter>libs\vmath</Filter>
   5.118 +    </None>
   5.119 +    <None Include="libs\vmath\ray.inl">
   5.120 +      <Filter>libs\vmath</Filter>
   5.121 +    </None>
   5.122 +    <None Include="libs\vmath\vector.inl">
   5.123 +      <Filter>libs\vmath</Filter>
   5.124 +    </None>
   5.125 +    <None Include="libs\vmath\vmath.inl">
   5.126 +      <Filter>libs\vmath</Filter>
   5.127 +    </None>
   5.128    </ItemGroup>
   5.129  </Project>
   5.130 \ No newline at end of file
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/libs/anim/anim.c	Sun Sep 29 08:20:19 2013 +0300
     6.3 @@ -0,0 +1,455 @@
     6.4 +#include <stdlib.h>
     6.5 +#include <limits.h>
     6.6 +#include <assert.h>
     6.7 +#include "anim.h"
     6.8 +#include "dynarr.h"
     6.9 +
    6.10 +#define ROT_USE_SLERP
    6.11 +
    6.12 +static void invalidate_cache(struct anm_node *node);
    6.13 +
    6.14 +int anm_init_node(struct anm_node *node)
    6.15 +{
    6.16 +	int i, j;
    6.17 +	static const float defaults[] = {
    6.18 +		0.0f, 0.0f, 0.0f,		/* default position */
    6.19 +		0.0f, 0.0f, 0.0f, 1.0f,	/* default rotation quat */
    6.20 +		1.0f, 1.0f, 1.0f		/* default scale factor */
    6.21 +	};
    6.22 +
    6.23 +	memset(node, 0, sizeof *node);
    6.24 +
    6.25 +	for(i=0; i<ANM_NUM_TRACKS; i++) {
    6.26 +		if(anm_init_track(node->tracks + i) == -1) {
    6.27 +			for(j=0; j<i; j++) {
    6.28 +				anm_destroy_track(node->tracks + i);
    6.29 +			}
    6.30 +		}
    6.31 +		anm_set_track_default(node->tracks + i, defaults[i]);
    6.32 +	}
    6.33 +
    6.34 +	node->cache.time = ANM_TIME_INVAL;
    6.35 +	node->cache.inv_time = ANM_TIME_INVAL;
    6.36 +	return 0;
    6.37 +}
    6.38 +
    6.39 +void anm_destroy_node(struct anm_node *node)
    6.40 +{
    6.41 +	int i;
    6.42 +	free(node->name);
    6.43 +
    6.44 +	for(i=0; i<ANM_NUM_TRACKS; i++) {
    6.45 +		anm_destroy_track(node->tracks + i);
    6.46 +	}
    6.47 +}
    6.48 +
    6.49 +void anm_destroy_node_tree(struct anm_node *tree)
    6.50 +{
    6.51 +	struct anm_node *c, *tmp;
    6.52 +
    6.53 +	if(!tree) return;
    6.54 +
    6.55 +	c = tree->child;
    6.56 +	while(c) {
    6.57 +		tmp = c;
    6.58 +		c = c->next;
    6.59 +
    6.60 +		anm_destroy_node_tree(tmp);
    6.61 +	}
    6.62 +	anm_destroy_node(tree);
    6.63 +}
    6.64 +
    6.65 +struct anm_node *anm_create_node(void)
    6.66 +{
    6.67 +	struct anm_node *n;
    6.68 +
    6.69 +	if((n = malloc(sizeof *n))) {
    6.70 +		if(anm_init_node(n) == -1) {
    6.71 +			free(n);
    6.72 +			return 0;
    6.73 +		}
    6.74 +	}
    6.75 +	return n;
    6.76 +}
    6.77 +
    6.78 +void anm_free_node(struct anm_node *node)
    6.79 +{
    6.80 +	anm_destroy_node(node);
    6.81 +	free(node);
    6.82 +}
    6.83 +
    6.84 +void anm_free_node_tree(struct anm_node *tree)
    6.85 +{
    6.86 +	struct anm_node *c, *tmp;
    6.87 +
    6.88 +	if(!tree) return;
    6.89 +
    6.90 +	c = tree->child;
    6.91 +	while(c) {
    6.92 +		tmp = c;
    6.93 +		c = c->next;
    6.94 +
    6.95 +		anm_free_node_tree(tmp);
    6.96 +	}
    6.97 +
    6.98 +	anm_free_node(tree);
    6.99 +}
   6.100 +
   6.101 +int anm_set_node_name(struct anm_node *node, const char *name)
   6.102 +{
   6.103 +	char *str;
   6.104 +
   6.105 +	if(!(str = malloc(strlen(name) + 1))) {
   6.106 +		return -1;
   6.107 +	}
   6.108 +	strcpy(str, name);
   6.109 +	free(node->name);
   6.110 +	node->name = str;
   6.111 +	return 0;
   6.112 +}
   6.113 +
   6.114 +const char *anm_get_node_name(struct anm_node *node)
   6.115 +{
   6.116 +	return node->name ? node->name : "";
   6.117 +}
   6.118 +
   6.119 +void anm_set_interpolator(struct anm_node *node, enum anm_interpolator in)
   6.120 +{
   6.121 +	int i;
   6.122 +
   6.123 +	for(i=0; i<ANM_NUM_TRACKS; i++) {
   6.124 +		anm_set_track_interpolator(node->tracks + i, in);
   6.125 +	}
   6.126 +	invalidate_cache(node);
   6.127 +}
   6.128 +
   6.129 +void anm_set_extrapolator(struct anm_node *node, enum anm_extrapolator ex)
   6.130 +{
   6.131 +	int i;
   6.132 +
   6.133 +	for(i=0; i<ANM_NUM_TRACKS; i++) {
   6.134 +		anm_set_track_extrapolator(node->tracks + i, ex);
   6.135 +	}
   6.136 +	invalidate_cache(node);
   6.137 +}
   6.138 +
   6.139 +void anm_link_node(struct anm_node *p, struct anm_node *c)
   6.140 +{
   6.141 +	c->next = p->child;
   6.142 +	p->child = c;
   6.143 +
   6.144 +	c->parent = p;
   6.145 +	invalidate_cache(c);
   6.146 +}
   6.147 +
   6.148 +int anm_unlink_node(struct anm_node *p, struct anm_node *c)
   6.149 +{
   6.150 +	struct anm_node *iter;
   6.151 +
   6.152 +	if(p->child == c) {
   6.153 +		p->child = c->next;
   6.154 +		c->next = 0;
   6.155 +		invalidate_cache(c);
   6.156 +		return 0;
   6.157 +	}
   6.158 +
   6.159 +	iter = p->child;
   6.160 +	while(iter->next) {
   6.161 +		if(iter->next == c) {
   6.162 +			iter->next = c->next;
   6.163 +			c->next = 0;
   6.164 +			invalidate_cache(c);
   6.165 +			return 0;
   6.166 +		}
   6.167 +	}
   6.168 +	return -1;
   6.169 +}
   6.170 +
   6.171 +void anm_set_position(struct anm_node *node, vec3_t pos, anm_time_t tm)
   6.172 +{
   6.173 +	anm_set_value(node->tracks + ANM_TRACK_POS_X, tm, pos.x);
   6.174 +	anm_set_value(node->tracks + ANM_TRACK_POS_Y, tm, pos.y);
   6.175 +	anm_set_value(node->tracks + ANM_TRACK_POS_Z, tm, pos.z);
   6.176 +	invalidate_cache(node);
   6.177 +}
   6.178 +
   6.179 +vec3_t anm_get_node_position(struct anm_node *node, anm_time_t tm)
   6.180 +{
   6.181 +	vec3_t v;
   6.182 +	v.x = anm_get_value(node->tracks + ANM_TRACK_POS_X, tm);
   6.183 +	v.y = anm_get_value(node->tracks + ANM_TRACK_POS_Y, tm);
   6.184 +	v.z = anm_get_value(node->tracks + ANM_TRACK_POS_Z, tm);
   6.185 +	return v;
   6.186 +}
   6.187 +
   6.188 +void anm_set_rotation(struct anm_node *node, quat_t rot, anm_time_t tm)
   6.189 +{
   6.190 +	anm_set_value(node->tracks + ANM_TRACK_ROT_X, tm, rot.x);
   6.191 +	anm_set_value(node->tracks + ANM_TRACK_ROT_Y, tm, rot.y);
   6.192 +	anm_set_value(node->tracks + ANM_TRACK_ROT_Z, tm, rot.z);
   6.193 +	anm_set_value(node->tracks + ANM_TRACK_ROT_W, tm, rot.w);
   6.194 +	invalidate_cache(node);
   6.195 +}
   6.196 +
   6.197 +quat_t anm_get_node_rotation(struct anm_node *node, anm_time_t tm)
   6.198 +{
   6.199 +#ifndef ROT_USE_SLERP
   6.200 +	quat_t q;
   6.201 +	q.x = anm_get_value(node->tracks + ANM_TRACK_ROT_X, tm);
   6.202 +	q.y = anm_get_value(node->tracks + ANM_TRACK_ROT_Y, tm);
   6.203 +	q.z = anm_get_value(node->tracks + ANM_TRACK_ROT_Z, tm);
   6.204 +	q.w = anm_get_value(node->tracks + ANM_TRACK_ROT_W, tm);
   6.205 +	return q;
   6.206 +#else
   6.207 +	int idx0, idx1, last_idx;
   6.208 +	anm_time_t tstart, tend;
   6.209 +	float t, dt;
   6.210 +	struct anm_track *track_x, *track_y, *track_z, *track_w;
   6.211 +	quat_t q, q1, q2;
   6.212 +
   6.213 +	track_x = node->tracks + ANM_TRACK_ROT_X;
   6.214 +	track_y = node->tracks + ANM_TRACK_ROT_Y;
   6.215 +	track_z = node->tracks + ANM_TRACK_ROT_Z;
   6.216 +	track_w = node->tracks + ANM_TRACK_ROT_W;
   6.217 +
   6.218 +	if(!track_x->count) {
   6.219 +		q.x = track_x->def_val;
   6.220 +		q.y = track_y->def_val;
   6.221 +		q.z = track_z->def_val;
   6.222 +		q.w = track_w->def_val;
   6.223 +		return q;
   6.224 +	}
   6.225 +
   6.226 +	last_idx = track_x->count - 1;
   6.227 +
   6.228 +	tstart = track_x->keys[0].time;
   6.229 +	tend = track_x->keys[last_idx].time;
   6.230 +
   6.231 +	if(tstart == tend) {
   6.232 +		q.x = track_x->keys[0].val;
   6.233 +		q.y = track_y->keys[0].val;
   6.234 +		q.z = track_z->keys[0].val;
   6.235 +		q.w = track_w->keys[0].val;
   6.236 +		return q;
   6.237 +	}
   6.238 +
   6.239 +	tm = anm_remap_time(track_x, tm, tstart, tend);
   6.240 +
   6.241 +	idx0 = anm_get_key_interval(track_x, tm);
   6.242 +	assert(idx0 >= 0 && idx0 < track_x->count);
   6.243 +	idx1 = idx0 + 1;
   6.244 +
   6.245 +	if(idx0 == last_idx) {
   6.246 +		q.x = track_x->keys[idx0].val;
   6.247 +		q.y = track_y->keys[idx0].val;
   6.248 +		q.z = track_z->keys[idx0].val;
   6.249 +		q.w = track_w->keys[idx0].val;
   6.250 +		return q;
   6.251 +	}
   6.252 +
   6.253 +	dt = (float)(track_x->keys[idx1].time - track_x->keys[idx0].time);
   6.254 +	t = (float)(tm - track_x->keys[idx0].time) / dt;
   6.255 +
   6.256 +	q1.x = track_x->keys[idx0].val;
   6.257 +	q1.y = track_y->keys[idx0].val;
   6.258 +	q1.z = track_z->keys[idx0].val;
   6.259 +	q1.w = track_w->keys[idx0].val;
   6.260 +
   6.261 +	q2.x = track_x->keys[idx1].val;
   6.262 +	q2.y = track_y->keys[idx1].val;
   6.263 +	q2.z = track_z->keys[idx1].val;
   6.264 +	q2.w = track_w->keys[idx1].val;
   6.265 +
   6.266 +	/*q1 = quat_normalize(q1);
   6.267 +	q2 = quat_normalize(q2);*/
   6.268 +
   6.269 +	return quat_slerp(q1, q2, t);
   6.270 +#endif
   6.271 +}
   6.272 +
   6.273 +void anm_set_scaling(struct anm_node *node, vec3_t scl, anm_time_t tm)
   6.274 +{
   6.275 +	anm_set_value(node->tracks + ANM_TRACK_SCL_X, tm, scl.x);
   6.276 +	anm_set_value(node->tracks + ANM_TRACK_SCL_Y, tm, scl.y);
   6.277 +	anm_set_value(node->tracks + ANM_TRACK_SCL_Z, tm, scl.z);
   6.278 +	invalidate_cache(node);
   6.279 +}
   6.280 +
   6.281 +vec3_t anm_get_node_scaling(struct anm_node *node, anm_time_t tm)
   6.282 +{
   6.283 +	vec3_t v;
   6.284 +	v.x = anm_get_value(node->tracks + ANM_TRACK_SCL_X, tm);
   6.285 +	v.y = anm_get_value(node->tracks + ANM_TRACK_SCL_Y, tm);
   6.286 +	v.z = anm_get_value(node->tracks + ANM_TRACK_SCL_Z, tm);
   6.287 +	return v;
   6.288 +}
   6.289 +
   6.290 +
   6.291 +vec3_t anm_get_position(struct anm_node *node, anm_time_t tm)
   6.292 +{
   6.293 +	mat4_t xform;
   6.294 +	vec3_t pos = {0.0, 0.0, 0.0};
   6.295 +
   6.296 +	if(!node->parent) {
   6.297 +		return anm_get_node_position(node, tm);
   6.298 +	}
   6.299 +
   6.300 +	anm_get_matrix(node, xform, tm);
   6.301 +	return v3_transform(pos, xform);
   6.302 +}
   6.303 +
   6.304 +quat_t anm_get_rotation(struct anm_node *node, anm_time_t tm)
   6.305 +{
   6.306 +	quat_t rot, prot;
   6.307 +	rot = anm_get_node_rotation(node, tm);
   6.308 +
   6.309 +	if(!node->parent) {
   6.310 +		return rot;
   6.311 +	}
   6.312 +
   6.313 +	prot = anm_get_rotation(node->parent, tm);
   6.314 +	return quat_mul(prot, rot);
   6.315 +}
   6.316 +
   6.317 +vec3_t anm_get_scaling(struct anm_node *node, anm_time_t tm)
   6.318 +{
   6.319 +	vec3_t s, ps;
   6.320 +	s = anm_get_node_scaling(node, tm);
   6.321 +
   6.322 +	if(!node->parent) {
   6.323 +		return s;
   6.324 +	}
   6.325 +
   6.326 +	ps = anm_get_scaling(node->parent, tm);
   6.327 +	return v3_mul(s, ps);
   6.328 +}
   6.329 +
   6.330 +void anm_set_pivot(struct anm_node *node, vec3_t piv)
   6.331 +{
   6.332 +	node->pivot = piv;
   6.333 +}
   6.334 +
   6.335 +vec3_t anm_get_pivot(struct anm_node *node)
   6.336 +{
   6.337 +	return node->pivot;
   6.338 +}
   6.339 +
   6.340 +void anm_get_node_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm)
   6.341 +{
   6.342 +	int i;
   6.343 +	mat4_t rmat;
   6.344 +	vec3_t pos, scale;
   6.345 +	quat_t rot;
   6.346 +
   6.347 +	pos = anm_get_node_position(node, tm);
   6.348 +	rot = anm_get_node_rotation(node, tm);
   6.349 +	scale = anm_get_node_scaling(node, tm);
   6.350 +
   6.351 +	m4_set_translation(mat, node->pivot.x, node->pivot.y, node->pivot.z);
   6.352 +
   6.353 +	quat_to_mat4(rmat, rot);
   6.354 +	for(i=0; i<3; i++) {
   6.355 +		mat[i][0] = rmat[i][0];
   6.356 +		mat[i][1] = rmat[i][1];
   6.357 +		mat[i][2] = rmat[i][2];
   6.358 +	}
   6.359 +	/* this loop is equivalent to: m4_mult(mat, mat, rmat); */
   6.360 +
   6.361 +	mat[0][0] *= scale.x; mat[0][1] *= scale.y; mat[0][2] *= scale.z; mat[0][3] += pos.x;
   6.362 +	mat[1][0] *= scale.x; mat[1][1] *= scale.y; mat[1][2] *= scale.z; mat[1][3] += pos.y;
   6.363 +	mat[2][0] *= scale.x; mat[2][1] *= scale.y; mat[2][2] *= scale.z; mat[2][3] += pos.z;
   6.364 +
   6.365 +	m4_translate(mat, -node->pivot.x, -node->pivot.y, -node->pivot.z);
   6.366 +
   6.367 +	/* that's basically: pivot * rotation * translation * scaling * -pivot */
   6.368 +}
   6.369 +
   6.370 +void anm_get_node_inv_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm)
   6.371 +{
   6.372 +	mat4_t tmp;
   6.373 +	anm_get_node_matrix(node, tmp, tm);
   6.374 +	m4_inverse(mat, tmp);
   6.375 +}
   6.376 +
   6.377 +void anm_get_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm)
   6.378 +{
   6.379 +	if(node->cache.time != tm) {
   6.380 +		anm_get_node_matrix(node, node->cache.matrix, tm);
   6.381 +
   6.382 +		if(node->parent) {
   6.383 +			mat4_t parent_mat;
   6.384 +
   6.385 +			anm_get_matrix(node->parent, parent_mat, tm);
   6.386 +			m4_mult(node->cache.matrix, parent_mat, node->cache.matrix);
   6.387 +		}
   6.388 +		node->cache.time = tm;
   6.389 +	}
   6.390 +	m4_copy(mat, node->cache.matrix);
   6.391 +}
   6.392 +
   6.393 +void anm_get_inv_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm)
   6.394 +{
   6.395 +	if(node->cache.inv_time != tm) {
   6.396 +		anm_get_matrix(node, mat, tm);
   6.397 +		m4_inverse(node->cache.inv_matrix, mat);
   6.398 +		node->cache.inv_time = tm;
   6.399 +	}
   6.400 +	m4_copy(mat, node->cache.inv_matrix);
   6.401 +}
   6.402 +
   6.403 +anm_time_t anm_get_start_time(struct anm_node *node)
   6.404 +{
   6.405 +	int i;
   6.406 +	struct anm_node *c;
   6.407 +	anm_time_t res = LONG_MAX;
   6.408 +
   6.409 +	for(i=0; i<ANM_NUM_TRACKS; i++) {
   6.410 +		if(node->tracks[i].count) {
   6.411 +			anm_time_t tm = node->tracks[i].keys[0].time;
   6.412 +			if(tm < res) {
   6.413 +				res = tm;
   6.414 +			}
   6.415 +		}
   6.416 +	}
   6.417 +
   6.418 +	c = node->child;
   6.419 +	while(c) {
   6.420 +		anm_time_t tm = anm_get_start_time(c);
   6.421 +		if(tm < res) {
   6.422 +			res = tm;
   6.423 +		}
   6.424 +		c = c->next;
   6.425 +	}
   6.426 +	return res;
   6.427 +}
   6.428 +
   6.429 +anm_time_t anm_get_end_time(struct anm_node *node)
   6.430 +{
   6.431 +	int i;
   6.432 +	struct anm_node *c;
   6.433 +	anm_time_t res = LONG_MIN;
   6.434 +
   6.435 +	for(i=0; i<ANM_NUM_TRACKS; i++) {
   6.436 +		if(node->tracks[i].count) {
   6.437 +			anm_time_t tm = node->tracks[i].keys[node->tracks[i].count - 1].time;
   6.438 +			if(tm > res) {
   6.439 +				res = tm;
   6.440 +			}
   6.441 +		}
   6.442 +	}
   6.443 +
   6.444 +	c = node->child;
   6.445 +	while(c) {
   6.446 +		anm_time_t tm = anm_get_end_time(c);
   6.447 +		if(tm > res) {
   6.448 +			res = tm;
   6.449 +		}
   6.450 +		c = c->next;
   6.451 +	}
   6.452 +	return res;
   6.453 +}
   6.454 +
   6.455 +static void invalidate_cache(struct anm_node *node)
   6.456 +{
   6.457 +	node->cache.time = node->cache.inv_time = ANM_TIME_INVAL;
   6.458 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/libs/anim/anim.h	Sun Sep 29 08:20:19 2013 +0300
     7.3 @@ -0,0 +1,112 @@
     7.4 +#ifndef LIBANIM_H_
     7.5 +#define LIBANIM_H_
     7.6 +
     7.7 +#include "config.h"
     7.8 +
     7.9 +#include <vmath/vector.h>
    7.10 +#include <vmath/quat.h>
    7.11 +#include <vmath/matrix.h>
    7.12 +#include "track.h"
    7.13 +
    7.14 +enum {
    7.15 +	ANM_TRACK_POS_X,
    7.16 +	ANM_TRACK_POS_Y,
    7.17 +	ANM_TRACK_POS_Z,
    7.18 +
    7.19 +	ANM_TRACK_ROT_X,
    7.20 +	ANM_TRACK_ROT_Y,
    7.21 +	ANM_TRACK_ROT_Z,
    7.22 +	ANM_TRACK_ROT_W,
    7.23 +
    7.24 +	ANM_TRACK_SCL_X,
    7.25 +	ANM_TRACK_SCL_Y,
    7.26 +	ANM_TRACK_SCL_Z,
    7.27 +
    7.28 +	ANM_NUM_TRACKS
    7.29 +};
    7.30 +
    7.31 +struct anm_node {
    7.32 +	char *name;
    7.33 +
    7.34 +	struct anm_track tracks[ANM_NUM_TRACKS];
    7.35 +	vec3_t pivot;
    7.36 +
    7.37 +	/* matrix cache */
    7.38 +	struct mat_cache {
    7.39 +		mat4_t matrix, inv_matrix;
    7.40 +		anm_time_t time, inv_time;
    7.41 +	} cache;
    7.42 +
    7.43 +	struct anm_node *parent;
    7.44 +	struct anm_node *child;
    7.45 +	struct anm_node *next;
    7.46 +};
    7.47 +
    7.48 +#ifdef __cplusplus
    7.49 +extern "C" {
    7.50 +#endif
    7.51 +
    7.52 +/* node constructor and destructor */
    7.53 +int anm_init_node(struct anm_node *node);
    7.54 +void anm_destroy_node(struct anm_node *node);
    7.55 +
    7.56 +/* recursively destroy an animation node tree */
    7.57 +void anm_destroy_node_tree(struct anm_node *tree);
    7.58 +
    7.59 +/* helper functions to allocate/construct and destroy/free with
    7.60 + * a single call. They call anm_init_node and anm_destroy_node
    7.61 + * internally.
    7.62 + */
    7.63 +struct anm_node *anm_create_node(void);
    7.64 +void anm_free_node(struct anm_node *node);
    7.65 +
    7.66 +/* recursively destroy and free the nodes of a node tree */
    7.67 +void anm_free_node_tree(struct anm_node *tree);
    7.68 +
    7.69 +int anm_set_node_name(struct anm_node *node, const char *name);
    7.70 +const char *anm_get_node_name(struct anm_node *node);
    7.71 +
    7.72 +void anm_set_interpolator(struct anm_node *node, enum anm_interpolator in);
    7.73 +void anm_set_extrapolator(struct anm_node *node, enum anm_extrapolator ex);
    7.74 +
    7.75 +/* link and unlink nodes with parent/child relations */
    7.76 +void anm_link_node(struct anm_node *parent, struct anm_node *child);
    7.77 +int anm_unlink_node(struct anm_node *parent, struct anm_node *child);
    7.78 +
    7.79 +void anm_set_position(struct anm_node *node, vec3_t pos, anm_time_t tm);
    7.80 +vec3_t anm_get_node_position(struct anm_node *node, anm_time_t tm);
    7.81 +
    7.82 +void anm_set_rotation(struct anm_node *node, quat_t rot, anm_time_t tm);
    7.83 +quat_t anm_get_node_rotation(struct anm_node *node, anm_time_t tm);
    7.84 +
    7.85 +void anm_set_scaling(struct anm_node *node, vec3_t scl, anm_time_t tm);
    7.86 +vec3_t anm_get_node_scaling(struct anm_node *node, anm_time_t tm);
    7.87 +
    7.88 +/* these three return the full p/r/s taking hierarchy into account */
    7.89 +vec3_t anm_get_position(struct anm_node *node, anm_time_t tm);
    7.90 +quat_t anm_get_rotation(struct anm_node *node, anm_time_t tm);
    7.91 +vec3_t anm_get_scaling(struct anm_node *node, anm_time_t tm);
    7.92 +
    7.93 +void anm_set_pivot(struct anm_node *node, vec3_t pivot);
    7.94 +vec3_t anm_get_pivot(struct anm_node *node);
    7.95 +
    7.96 +/* these calculate the matrix and inverse matrix of this node alone */
    7.97 +void anm_get_node_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm);
    7.98 +void anm_get_node_inv_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm);
    7.99 +
   7.100 +/* These calculate the matrix and inverse matrix of this node taking hierarchy
   7.101 + * into account. The results are cached in thread-specific storage and returned
   7.102 + * if there's no change in time or tracks from the last query...
   7.103 + */
   7.104 +void anm_get_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm);
   7.105 +void anm_get_inv_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm);
   7.106 +
   7.107 +/* those return the start and end times of the whole tree */
   7.108 +anm_time_t anm_get_start_time(struct anm_node *node);
   7.109 +anm_time_t anm_get_end_time(struct anm_node *node);
   7.110 +
   7.111 +#ifdef __cplusplus
   7.112 +}
   7.113 +#endif
   7.114 +
   7.115 +#endif	/* LIBANIM_H_ */
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/libs/anim/config.h	Sun Sep 29 08:20:19 2013 +0300
     8.3 @@ -0,0 +1,6 @@
     8.4 +#ifndef ANIM_CONFIG_H_
     8.5 +#define ANIM_CONFIG_H_
     8.6 +
     8.7 +#undef ANIM_THREAD_SAFE
     8.8 +
     8.9 +#endif	/* ANIM_CONFIG_H_ */
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/libs/anim/dynarr.c	Sun Sep 29 08:20:19 2013 +0300
     9.3 @@ -0,0 +1,122 @@
     9.4 +#include <stdio.h>
     9.5 +#include <stdlib.h>
     9.6 +#include <string.h>
     9.7 +#include "dynarr.h"
     9.8 +
     9.9 +/* The array descriptor keeps auxilliary information needed to manipulate
    9.10 + * the dynamic array. It's allocated adjacent to the array buffer.
    9.11 + */
    9.12 +struct arrdesc {
    9.13 +	int nelem, szelem;
    9.14 +	int max_elem;
    9.15 +	int bufsz;	/* not including the descriptor */
    9.16 +};
    9.17 +
    9.18 +#define DESC(x)		((struct arrdesc*)((char*)(x) - sizeof(struct arrdesc)))
    9.19 +
    9.20 +void *dynarr_alloc(int elem, int szelem)
    9.21 +{
    9.22 +	struct arrdesc *desc;
    9.23 +
    9.24 +	if(!(desc = malloc(elem * szelem + sizeof *desc))) {
    9.25 +		return 0;
    9.26 +	}
    9.27 +	desc->nelem = desc->max_elem = elem;
    9.28 +	desc->szelem = szelem;
    9.29 +	desc->bufsz = elem * szelem;
    9.30 +	return (char*)desc + sizeof *desc;
    9.31 +}
    9.32 +
    9.33 +void dynarr_free(void *da)
    9.34 +{
    9.35 +	if(da) {
    9.36 +		free(DESC(da));
    9.37 +	}
    9.38 +}
    9.39 +
    9.40 +void *dynarr_resize(void *da, int elem)
    9.41 +{
    9.42 +	int newsz;
    9.43 +	void *tmp;
    9.44 +	struct arrdesc *desc;
    9.45 +
    9.46 +	if(!da) return 0;
    9.47 +	desc = DESC(da);
    9.48 +
    9.49 +	newsz = desc->szelem * elem;
    9.50 +
    9.51 +	if(!(tmp = realloc(desc, newsz + sizeof *desc))) {
    9.52 +		return 0;
    9.53 +	}
    9.54 +	desc = tmp;
    9.55 +
    9.56 +	desc->nelem = desc->max_elem = elem;
    9.57 +	desc->bufsz = newsz;
    9.58 +	return (char*)desc + sizeof *desc;
    9.59 +}
    9.60 +
    9.61 +int dynarr_empty(void *da)
    9.62 +{
    9.63 +	return DESC(da)->nelem ? 0 : 1;
    9.64 +}
    9.65 +
    9.66 +int dynarr_size(void *da)
    9.67 +{
    9.68 +	return DESC(da)->nelem;
    9.69 +}
    9.70 +
    9.71 +
    9.72 +/* stack semantics */
    9.73 +void *dynarr_push(void *da, void *item)
    9.74 +{
    9.75 +	struct arrdesc *desc;
    9.76 +	int nelem;
    9.77 +
    9.78 +	desc = DESC(da);
    9.79 +	nelem = desc->nelem;
    9.80 +
    9.81 +	if(nelem >= desc->max_elem) {
    9.82 +		/* need to resize */
    9.83 +		struct arrdesc *tmp;
    9.84 +		int newsz = desc->max_elem ? desc->max_elem * 2 : 1;
    9.85 +
    9.86 +		if(!(tmp = dynarr_resize(da, newsz))) {
    9.87 +			fprintf(stderr, "failed to resize\n");
    9.88 +			return da;
    9.89 +		}
    9.90 +		da = tmp;
    9.91 +		desc = DESC(da);
    9.92 +		desc->nelem = nelem;
    9.93 +	}
    9.94 +
    9.95 +	memcpy((char*)da + desc->nelem++ * desc->szelem, item, desc->szelem);
    9.96 +	return da;
    9.97 +}
    9.98 +
    9.99 +void *dynarr_pop(void *da)
   9.100 +{
   9.101 +	struct arrdesc *desc;
   9.102 +	int nelem;
   9.103 +
   9.104 +	desc = DESC(da);
   9.105 +	nelem = desc->nelem;
   9.106 +
   9.107 +	if(!nelem) return da;
   9.108 +
   9.109 +	if(nelem <= desc->max_elem / 3) {
   9.110 +		/* reclaim space */
   9.111 +		struct arrdesc *tmp;
   9.112 +		int newsz = desc->max_elem / 2;
   9.113 +
   9.114 +		if(!(tmp = dynarr_resize(da, newsz))) {
   9.115 +			fprintf(stderr, "failed to resize\n");
   9.116 +			return da;
   9.117 +		}
   9.118 +		da = tmp;
   9.119 +		desc = DESC(da);
   9.120 +		desc->nelem = nelem;
   9.121 +	}
   9.122 +	desc->nelem--;
   9.123 +
   9.124 +	return da;
   9.125 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/libs/anim/dynarr.h	Sun Sep 29 08:20:19 2013 +0300
    10.3 @@ -0,0 +1,18 @@
    10.4 +#ifndef DYNARR_H_
    10.5 +#define DYNARR_H_
    10.6 +
    10.7 +#include "config.h"
    10.8 +
    10.9 +void *dynarr_alloc(int elem, int szelem);
   10.10 +void dynarr_free(void *da);
   10.11 +void *dynarr_resize(void *da, int elem);
   10.12 +
   10.13 +int dynarr_empty(void *da);
   10.14 +int dynarr_size(void *da);
   10.15 +
   10.16 +/* stack semantics */
   10.17 +void *dynarr_push(void *da, void *item);
   10.18 +void *dynarr_pop(void *da);
   10.19 +
   10.20 +
   10.21 +#endif	/* DYNARR_H_ */
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/libs/anim/track.c	Sun Sep 29 08:20:19 2013 +0300
    11.3 @@ -0,0 +1,316 @@
    11.4 +#include <stdlib.h>
    11.5 +#include <string.h>
    11.6 +#include <assert.h>
    11.7 +#include "track.h"
    11.8 +#include "dynarr.h"
    11.9 +
   11.10 +static int keycmp(const void *a, const void *b);
   11.11 +static int find_prev_key(struct anm_keyframe *arr, int start, int end, anm_time_t tm);
   11.12 +
   11.13 +static float interp_step(float v0, float v1, float v2, float v3, float t);
   11.14 +static float interp_linear(float v0, float v1, float v2, float v3, float t);
   11.15 +static float interp_cubic(float v0, float v1, float v2, float v3, float t);
   11.16 +
   11.17 +static anm_time_t remap_extend(anm_time_t tm, anm_time_t start, anm_time_t end);
   11.18 +static anm_time_t remap_clamp(anm_time_t tm, anm_time_t start, anm_time_t end);
   11.19 +static anm_time_t remap_repeat(anm_time_t tm, anm_time_t start, anm_time_t end);
   11.20 +static anm_time_t remap_pingpong(anm_time_t tm, anm_time_t start, anm_time_t end);
   11.21 +
   11.22 +/* XXX keep this in sync with enum anm_interpolator at track.h */
   11.23 +static float (*interp[])(float, float, float, float, float) = {
   11.24 +	interp_step,
   11.25 +	interp_linear,
   11.26 +	interp_cubic,
   11.27 +	0
   11.28 +};
   11.29 +
   11.30 +/* XXX keep this in sync with enum anm_extrapolator at track.h */
   11.31 +static anm_time_t (*remap_time[])(anm_time_t, anm_time_t, anm_time_t) = {
   11.32 +	remap_extend,
   11.33 +	remap_clamp,
   11.34 +	remap_repeat,
   11.35 +	remap_pingpong,
   11.36 +	0
   11.37 +};
   11.38 +
   11.39 +int anm_init_track(struct anm_track *track)
   11.40 +{
   11.41 +	memset(track, 0, sizeof *track);
   11.42 +
   11.43 +	if(!(track->keys = dynarr_alloc(0, sizeof *track->keys))) {
   11.44 +		return -1;
   11.45 +	}
   11.46 +	track->interp = ANM_INTERP_LINEAR;
   11.47 +	track->extrap = ANM_EXTRAP_CLAMP;
   11.48 +	return 0;
   11.49 +}
   11.50 +
   11.51 +void anm_destroy_track(struct anm_track *track)
   11.52 +{
   11.53 +	dynarr_free(track->keys);
   11.54 +}
   11.55 +
   11.56 +struct anm_track *anm_create_track(void)
   11.57 +{
   11.58 +	struct anm_track *track;
   11.59 +
   11.60 +	if((track = malloc(sizeof *track))) {
   11.61 +		if(anm_init_track(track) == -1) {
   11.62 +			free(track);
   11.63 +			return 0;
   11.64 +		}
   11.65 +	}
   11.66 +	return track;
   11.67 +}
   11.68 +
   11.69 +void anm_free_track(struct anm_track *track)
   11.70 +{
   11.71 +	anm_destroy_track(track);
   11.72 +	free(track);
   11.73 +}
   11.74 +
   11.75 +void anm_copy_track(struct anm_track *dest, struct anm_track *src)
   11.76 +{
   11.77 +	free(dest->name);
   11.78 +	if(dest->keys) {
   11.79 +		dynarr_free(dest->keys);
   11.80 +	}
   11.81 +
   11.82 +	if(src->name) {
   11.83 +		dest->name = malloc(strlen(src->name) + 1);
   11.84 +		strcpy(dest->name, src->name);
   11.85 +	}
   11.86 +
   11.87 +	dest->count = src->count;
   11.88 +	dest->keys = dynarr_alloc(src->count, sizeof *dest->keys);
   11.89 +	memcpy(dest->keys, src->keys, src->count * sizeof *dest->keys);
   11.90 +
   11.91 +	dest->def_val = src->def_val;
   11.92 +	dest->interp = src->interp;
   11.93 +	dest->extrap = src->extrap;
   11.94 +}
   11.95 +
   11.96 +int anm_set_track_name(struct anm_track *track, const char *name)
   11.97 +{
   11.98 +	char *tmp;
   11.99 +
  11.100 +	if(!(tmp = malloc(strlen(name) + 1))) {
  11.101 +		return -1;
  11.102 +	}
  11.103 +	free(track->name);
  11.104 +	track->name = tmp;
  11.105 +	return 0;
  11.106 +}
  11.107 +
  11.108 +const char *anm_get_track_name(struct anm_track *track)
  11.109 +{
  11.110 +	return track->name;
  11.111 +}
  11.112 +
  11.113 +void anm_set_track_interpolator(struct anm_track *track, enum anm_interpolator in)
  11.114 +{
  11.115 +	track->interp = in;
  11.116 +}
  11.117 +
  11.118 +void anm_set_track_extrapolator(struct anm_track *track, enum anm_extrapolator ex)
  11.119 +{
  11.120 +	track->extrap = ex;
  11.121 +}
  11.122 +
  11.123 +anm_time_t anm_remap_time(struct anm_track *track, anm_time_t tm, anm_time_t start, anm_time_t end)
  11.124 +{
  11.125 +	return remap_time[track->extrap](tm, start, end);
  11.126 +}
  11.127 +
  11.128 +void anm_set_track_default(struct anm_track *track, float def)
  11.129 +{
  11.130 +	track->def_val = def;
  11.131 +}
  11.132 +
  11.133 +int anm_set_keyframe(struct anm_track *track, struct anm_keyframe *key)
  11.134 +{
  11.135 +	int idx = anm_get_key_interval(track, key->time);
  11.136 +
  11.137 +	/* if we got a valid keyframe index, compare them... */
  11.138 +	if(idx >= 0 && idx < track->count && keycmp(key, track->keys + idx) == 0) {
  11.139 +		/* ... it's the same key, just update the value */
  11.140 +		track->keys[idx].val = key->val;
  11.141 +	} else {
  11.142 +		/* ... it's a new key, add it and re-sort them */
  11.143 +		void *tmp;
  11.144 +		if(!(tmp = dynarr_push(track->keys, key))) {
  11.145 +			return -1;
  11.146 +		}
  11.147 +		track->keys = tmp;
  11.148 +		/* TODO lazy qsort */
  11.149 +		qsort(track->keys, ++track->count, sizeof *track->keys, keycmp);
  11.150 +	}
  11.151 +	return 0;
  11.152 +}
  11.153 +
  11.154 +static int keycmp(const void *a, const void *b)
  11.155 +{
  11.156 +	return ((struct anm_keyframe*)a)->time - ((struct anm_keyframe*)b)->time;
  11.157 +}
  11.158 +
  11.159 +struct anm_keyframe *anm_get_keyframe(struct anm_track *track, int idx)
  11.160 +{
  11.161 +	if(idx < 0 || idx >= track->count) {
  11.162 +		return 0;
  11.163 +	}
  11.164 +	return track->keys + idx;
  11.165 +}
  11.166 +
  11.167 +int anm_get_key_interval(struct anm_track *track, anm_time_t tm)
  11.168 +{
  11.169 +	int last;
  11.170 +
  11.171 +	if(!track->count || tm < track->keys[0].time) {
  11.172 +		return -1;
  11.173 +	}
  11.174 +
  11.175 +	last = track->count - 1;
  11.176 +	if(tm > track->keys[last].time) {
  11.177 +		return last;
  11.178 +	}
  11.179 +
  11.180 +	return find_prev_key(track->keys, 0, last, tm);
  11.181 +}
  11.182 +
  11.183 +static int find_prev_key(struct anm_keyframe *arr, int start, int end, anm_time_t tm)
  11.184 +{
  11.185 +	int mid;
  11.186 +
  11.187 +	if(end - start <= 1) {
  11.188 +		return start;
  11.189 +	}
  11.190 +
  11.191 +	mid = (start + end) / 2;
  11.192 +	if(tm < arr[mid].time) {
  11.193 +		return find_prev_key(arr, start, mid, tm);
  11.194 +	}
  11.195 +	if(tm > arr[mid].time) {
  11.196 +		return find_prev_key(arr, mid, end, tm);
  11.197 +	}
  11.198 +	return mid;
  11.199 +}
  11.200 +
  11.201 +int anm_set_value(struct anm_track *track, anm_time_t tm, float val)
  11.202 +{
  11.203 +	struct anm_keyframe key;
  11.204 +	key.time = tm;
  11.205 +	key.val = val;
  11.206 +
  11.207 +	return anm_set_keyframe(track, &key);
  11.208 +}
  11.209 +
  11.210 +float anm_get_value(struct anm_track *track, anm_time_t tm)
  11.211 +{
  11.212 +	int idx0, idx1, last_idx;
  11.213 +	anm_time_t tstart, tend;
  11.214 +	float t, dt;
  11.215 +	float v0, v1, v2, v3;
  11.216 +
  11.217 +	if(!track->count) {
  11.218 +		return track->def_val;
  11.219 +	}
  11.220 +
  11.221 +	last_idx = track->count - 1;
  11.222 +
  11.223 +	tstart = track->keys[0].time;
  11.224 +	tend = track->keys[last_idx].time;
  11.225 +
  11.226 +	if(tstart == tend) {
  11.227 +		return track->keys[0].val;
  11.228 +	}
  11.229 +
  11.230 +	tm = remap_time[track->extrap](tm, tstart, tend);
  11.231 +
  11.232 +	idx0 = anm_get_key_interval(track, tm);
  11.233 +	assert(idx0 >= 0 && idx0 < track->count);
  11.234 +	idx1 = idx0 + 1;
  11.235 +
  11.236 +	if(idx0 == last_idx) {
  11.237 +		return track->keys[idx0].val;
  11.238 +	}
  11.239 +
  11.240 +	dt = (float)(track->keys[idx1].time - track->keys[idx0].time);
  11.241 +	t = (float)(tm - track->keys[idx0].time) / dt;
  11.242 +
  11.243 +	v1 = track->keys[idx0].val;
  11.244 +	v2 = track->keys[idx1].val;
  11.245 +
  11.246 +	/* get the neigboring values to allow for cubic interpolation */
  11.247 +	v0 = idx0 > 0 ? track->keys[idx0 - 1].val : v1;
  11.248 +	v3 = idx1 < last_idx ? track->keys[idx1 + 1].val : v2;
  11.249 +
  11.250 +	return interp[track->interp](v0, v1, v2, v3, t);
  11.251 +}
  11.252 +
  11.253 +
  11.254 +static float interp_step(float v0, float v1, float v2, float v3, float t)
  11.255 +{
  11.256 +	return v1;
  11.257 +}
  11.258 +
  11.259 +static float interp_linear(float v0, float v1, float v2, float v3, float t)
  11.260 +{
  11.261 +	return v1 + (v2 - v1) * t;
  11.262 +}
  11.263 +
  11.264 +static float interp_cubic(float a, float b, float c, float d, float t)
  11.265 +{
  11.266 +	float x, y, z, w;
  11.267 +	float tsq = t * t;
  11.268 +
  11.269 +	x = -a + 3.0 * b - 3.0 * c + d;
  11.270 +	y = 2.0 * a - 5.0 * b + 4.0 * c - d;
  11.271 +	z = c - a;
  11.272 +	w = 2.0 * b;
  11.273 +
  11.274 +	return 0.5 * (x * tsq * t + y * tsq + z * t + w);
  11.275 +}
  11.276 +
  11.277 +static anm_time_t remap_extend(anm_time_t tm, anm_time_t start, anm_time_t end)
  11.278 +{
  11.279 +	return remap_repeat(tm, start, end);
  11.280 +}
  11.281 +
  11.282 +static anm_time_t remap_clamp(anm_time_t tm, anm_time_t start, anm_time_t end)
  11.283 +{
  11.284 +	if(start == end) {
  11.285 +		return start;
  11.286 +	}
  11.287 +	return tm < start ? start : (tm >= end ? end - 1 : tm);
  11.288 +}
  11.289 +
  11.290 +static anm_time_t remap_repeat(anm_time_t tm, anm_time_t start, anm_time_t end)
  11.291 +{
  11.292 +	anm_time_t x, interv = end - start;
  11.293 +
  11.294 +	if(interv == 0) {
  11.295 +		return start;
  11.296 +	}
  11.297 +
  11.298 +	x = (tm - start) % interv;
  11.299 +	if(x < 0) {
  11.300 +		x += interv;
  11.301 +	}
  11.302 +	return x + start;
  11.303 +
  11.304 +	/*if(tm < start) {
  11.305 +		while(tm < start) {
  11.306 +			tm += interv;
  11.307 +		}
  11.308 +		return tm;
  11.309 +	}
  11.310 +	return (tm - start) % interv + start;*/
  11.311 +}
  11.312 +
  11.313 +static anm_time_t remap_pingpong(anm_time_t tm, anm_time_t start, anm_time_t end)
  11.314 +{
  11.315 +	anm_time_t interv = end - start;
  11.316 +	anm_time_t x = remap_repeat(tm, start, end + interv);
  11.317 +
  11.318 +	return x > end ? end + interv - x : x;
  11.319 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/libs/anim/track.h	Sun Sep 29 08:20:19 2013 +0300
    12.3 @@ -0,0 +1,101 @@
    12.4 +/* An animation track defines the values of a single scalar over time
    12.5 + * and supports various interpolation and extrapolation modes.
    12.6 + */
    12.7 +#ifndef LIBANIM_TRACK_H_
    12.8 +#define LIBANIM_TRACK_H_
    12.9 +
   12.10 +#include <limits.h>
   12.11 +#include "config.h"
   12.12 +
   12.13 +enum anm_interpolator {
   12.14 +	ANM_INTERP_STEP,
   12.15 +	ANM_INTERP_LINEAR,
   12.16 +	ANM_INTERP_CUBIC
   12.17 +};
   12.18 +
   12.19 +enum anm_extrapolator {
   12.20 +	ANM_EXTRAP_EXTEND,	/* extend to infinity */
   12.21 +	ANM_EXTRAP_CLAMP,	/* clamp to last value */
   12.22 +	ANM_EXTRAP_REPEAT,	/* repeat motion */
   12.23 +	ANM_EXTRAP_PINGPONG	/* repeat with mirroring */
   12.24 +};
   12.25 +
   12.26 +typedef long anm_time_t;
   12.27 +#define ANM_TIME_INVAL	LONG_MIN
   12.28 +
   12.29 +#define ANM_SEC2TM(x)	((anm_time_t)((x) * 1000))
   12.30 +#define ANM_MSEC2TM(x)	((anm_time_t)(x))
   12.31 +#define ANM_TM2SEC(x)	((x) / 1000.0)
   12.32 +#define ANM_TM2MSEC(x)	(x)
   12.33 +
   12.34 +struct anm_keyframe {
   12.35 +	anm_time_t time;
   12.36 +	float val;
   12.37 +};
   12.38 +
   12.39 +struct anm_track {
   12.40 +	char *name;
   12.41 +	int count;
   12.42 +	struct anm_keyframe *keys;
   12.43 +
   12.44 +	float def_val;
   12.45 +
   12.46 +	enum anm_interpolator interp;
   12.47 +	enum anm_extrapolator extrap;
   12.48 +};
   12.49 +
   12.50 +#ifdef __cplusplus
   12.51 +extern "C" {
   12.52 +#endif
   12.53 +
   12.54 +/* track constructor and destructor */
   12.55 +int anm_init_track(struct anm_track *track);
   12.56 +void anm_destroy_track(struct anm_track *track);
   12.57 +
   12.58 +/* helper functions that use anm_init_track and anm_destroy_track internally */
   12.59 +struct anm_track *anm_create_track(void);
   12.60 +void anm_free_track(struct anm_track *track);
   12.61 +
   12.62 +/* copies track src to dest
   12.63 + * XXX: dest must have been initialized first
   12.64 + */
   12.65 +void anm_copy_track(struct anm_track *dest, struct anm_track *src);
   12.66 +
   12.67 +int anm_set_track_name(struct anm_track *track, const char *name);
   12.68 +const char *anm_get_track_name(struct anm_track *track);
   12.69 +
   12.70 +void anm_set_track_interpolator(struct anm_track *track, enum anm_interpolator in);
   12.71 +void anm_set_track_extrapolator(struct anm_track *track, enum anm_extrapolator ex);
   12.72 +
   12.73 +anm_time_t anm_remap_time(struct anm_track *track, anm_time_t tm, anm_time_t start, anm_time_t end);
   12.74 +
   12.75 +void anm_set_track_default(struct anm_track *track, float def);
   12.76 +
   12.77 +/* set or update a keyframe */
   12.78 +int anm_set_keyframe(struct anm_track *track, struct anm_keyframe *key);
   12.79 +
   12.80 +/* get the idx-th keyframe, returns null if it doesn't exist */
   12.81 +struct anm_keyframe *anm_get_keyframe(struct anm_track *track, int idx);
   12.82 +
   12.83 +/* Finds the 0-based index of the intra-keyframe interval which corresponds
   12.84 + * to the specified time. If the time falls exactly onto the N-th keyframe
   12.85 + * the function returns N.
   12.86 + *
   12.87 + * Special cases:
   12.88 + * - if the time is before the first keyframe -1 is returned.
   12.89 + * - if the time is after the last keyframe, the index of the last keyframe
   12.90 + *   is returned.
   12.91 + */
   12.92 +int anm_get_key_interval(struct anm_track *track, anm_time_t tm);
   12.93 +
   12.94 +int anm_set_value(struct anm_track *track, anm_time_t tm, float val);
   12.95 +
   12.96 +/* evaluates and returns the value of the track for a particular time */
   12.97 +float anm_get_value(struct anm_track *track, anm_time_t tm);
   12.98 +
   12.99 +#ifdef __cplusplus
  12.100 +}
  12.101 +#endif
  12.102 +
  12.103 +
  12.104 +#endif	/* LIBANIM_TRACK_H_ */
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/libs/vmath/basis.cc	Sun Sep 29 08:20:19 2013 +0300
    13.3 @@ -0,0 +1,63 @@
    13.4 +#include "basis.h"
    13.5 +#include "vmath.h"
    13.6 +
    13.7 +Basis::Basis()
    13.8 +{
    13.9 +	i = Vector3(1, 0, 0);
   13.10 +	j = Vector3(0, 1, 0);
   13.11 +	k = Vector3(0, 0, 1);
   13.12 +}
   13.13 +
   13.14 +Basis::Basis(const Vector3 &i, const Vector3 &j, const Vector3 &k)
   13.15 +{
   13.16 +	this->i = i;
   13.17 +	this->j = j;
   13.18 +	this->k = k;
   13.19 +}
   13.20 +
   13.21 +Basis::Basis(const Vector3 &dir, bool left_handed)
   13.22 +{
   13.23 +	k = dir;
   13.24 +	j = Vector3(0, 1, 0);
   13.25 +	i = cross_product(j, k);
   13.26 +	j = cross_product(k, i);
   13.27 +}
   13.28 +
   13.29 +/** Rotate with euler angles */
   13.30 +void Basis::rotate(scalar_t x, scalar_t y, scalar_t z) {
   13.31 +	Matrix4x4 RotMat;
   13.32 +	RotMat.set_rotation(Vector3(x, y, z));
   13.33 +	i.transform(RotMat);
   13.34 +	j.transform(RotMat);
   13.35 +	k.transform(RotMat);
   13.36 +}
   13.37 +
   13.38 +/** Rotate by axis-angle specification */
   13.39 +void Basis::rotate(const Vector3 &axis, scalar_t angle) {
   13.40 +	Quaternion q;
   13.41 +	q.set_rotation(axis, angle);
   13.42 +	i.transform(q);
   13.43 +	j.transform(q);
   13.44 +	k.transform(q);
   13.45 +}
   13.46 +
   13.47 +/** Rotate with a 4x4 matrix */
   13.48 +void Basis::rotate(const Matrix4x4 &mat) {
   13.49 +	i.transform(mat);
   13.50 +	j.transform(mat);
   13.51 +	k.transform(mat);
   13.52 +}
   13.53 +
   13.54 +/** Rotate with a quaternion */
   13.55 +void Basis::rotate(const Quaternion &quat) {
   13.56 +	i.transform(quat);
   13.57 +	j.transform(quat);
   13.58 +	k.transform(quat);
   13.59 +}
   13.60 +
   13.61 +/** Extract a rotation matrix from the orthogonal basis */
   13.62 +Matrix3x3 Basis::create_rotation_matrix() const {
   13.63 +	return Matrix3x3(	i.x, j.x, k.x,
   13.64 +						i.y, j.y, k.y,
   13.65 +						i.z, j.z, k.z);
   13.66 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/libs/vmath/basis.h	Sun Sep 29 08:20:19 2013 +0300
    14.3 @@ -0,0 +1,57 @@
    14.4 +/*
    14.5 +libvmath - a vector math library
    14.6 +Copyright (C) 2004-2011 John Tsiombikas <nuclear@member.fsf.org>
    14.7 +
    14.8 +This program is free software: you can redistribute it and/or modify
    14.9 +it under the terms of the GNU Lesser General Public License as published
   14.10 +by the Free Software Foundation, either version 3 of the License, or
   14.11 +(at your option) any later version.
   14.12 +
   14.13 +This program is distributed in the hope that it will be useful,
   14.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   14.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14.16 +GNU Lesser General Public License for more details.
   14.17 +
   14.18 +You should have received a copy of the GNU Lesser General Public License
   14.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
   14.20 +*/
   14.21 +
   14.22 +#ifndef VMATH_BASIS_H_
   14.23 +#define VMATH_BASIS_H_
   14.24 +
   14.25 +#include "vector.h"
   14.26 +#include "matrix.h"
   14.27 +
   14.28 +enum {
   14.29 +	LEFT_HANDED,
   14.30 +	RIGHT_HANDED
   14.31 +};
   14.32 +
   14.33 +#ifdef __cplusplus
   14.34 +extern "C" {
   14.35 +#endif	/* __cplusplus */
   14.36 +
   14.37 +void basis_matrix(mat4_t res, vec3_t i, vec3_t j, vec3_t k);
   14.38 +void basis_matrix_dir(mat4_t res, vec3_t dir);
   14.39 +
   14.40 +#ifdef __cplusplus
   14.41 +}	/* extern "C" */
   14.42 +
   14.43 +class Basis {
   14.44 +public:
   14.45 +	Vector3 i, j, k;
   14.46 +
   14.47 +	Basis();
   14.48 +	Basis(const Vector3 &i, const Vector3 &j, const Vector3 &k);
   14.49 +	Basis(const Vector3 &dir, bool left_handed = true);
   14.50 +
   14.51 +	void rotate(scalar_t x, scalar_t y, scalar_t z);
   14.52 +	void rotate(const Vector3 &axis, scalar_t angle);
   14.53 +	void rotate(const Matrix4x4 &mat);
   14.54 +	void rotate(const Quaternion &quat);
   14.55 +
   14.56 +	Matrix3x3 create_rotation_matrix() const;
   14.57 +};
   14.58 +#endif	/* __cplusplus */
   14.59 +
   14.60 +#endif	/* VMATH_BASIS_H_ */
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/libs/vmath/basis_c.c	Sun Sep 29 08:20:19 2013 +0300
    15.3 @@ -0,0 +1,37 @@
    15.4 +/*
    15.5 +libvmath - a vector math library
    15.6 +Copyright (C) 2004-2011 John Tsiombikas <nuclear@member.fsf.org>
    15.7 +
    15.8 +This program is free software: you can redistribute it and/or modify
    15.9 +it under the terms of the GNU Lesser General Public License as published
   15.10 +by the Free Software Foundation, either version 3 of the License, or
   15.11 +(at your option) any later version.
   15.12 +
   15.13 +This program is distributed in the hope that it will be useful,
   15.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   15.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15.16 +GNU Lesser General Public License for more details.
   15.17 +
   15.18 +You should have received a copy of the GNU Lesser General Public License
   15.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
   15.20 +*/
   15.21 +
   15.22 +#include "basis.h"
   15.23 +#include "matrix.h"
   15.24 +
   15.25 +void basis_matrix(mat4_t res, vec3_t i, vec3_t j, vec3_t k)
   15.26 +{
   15.27 +	m4_identity(res);
   15.28 +	m4_set_column(res, v4_cons(i.x, i.y, i.z, 1.0), 0);
   15.29 +	m4_set_column(res, v4_cons(j.x, j.y, j.z, 1.0), 1);
   15.30 +	m4_set_column(res, v4_cons(k.x, k.y, k.z, 1.0), 2);
   15.31 +}
   15.32 +
   15.33 +void basis_matrix_dir(mat4_t res, vec3_t dir)
   15.34 +{
   15.35 +	vec3_t k = v3_normalize(dir);
   15.36 +	vec3_t j = {0, 1, 0};
   15.37 +	vec3_t i = v3_cross(j, k);
   15.38 +	j = v3_cross(k, i);
   15.39 +	basis_matrix(res, i, j, k);
   15.40 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/libs/vmath/geom.c	Sun Sep 29 08:20:19 2013 +0300
    16.3 @@ -0,0 +1,150 @@
    16.4 +/*
    16.5 +libvmath - a vector math library
    16.6 +Copyright (C) 2004-2011 John Tsiombikas <nuclear@member.fsf.org>
    16.7 +
    16.8 +This program is free software: you can redistribute it and/or modify
    16.9 +it under the terms of the GNU Lesser General Public License as published
   16.10 +by the Free Software Foundation, either version 3 of the License, or
   16.11 +(at your option) any later version.
   16.12 +
   16.13 +This program is distributed in the hope that it will be useful,
   16.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   16.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16.16 +GNU Lesser General Public License for more details.
   16.17 +
   16.18 +You should have received a copy of the GNU Lesser General Public License
   16.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
   16.20 +*/
   16.21 +
   16.22 +
   16.23 +#include <math.h>
   16.24 +#include "geom.h"
   16.25 +#include "vector.h"
   16.26 +
   16.27 +plane_t plane_cons(scalar_t nx, scalar_t ny, scalar_t nz, scalar_t d)
   16.28 +{
   16.29 +	plane_t p;
   16.30 +	p.norm.x = nx;
   16.31 +	p.norm.y = ny;
   16.32 +	p.norm.z = nz;
   16.33 +	p.d = d;
   16.34 +	return p;
   16.35 +}
   16.36 +
   16.37 +plane_t plane_poly(vec3_t v0, vec3_t v1, vec3_t v2)
   16.38 +{
   16.39 +	vec3_t a, b, norm;
   16.40 +
   16.41 +	a = v3_sub(v1, v0);
   16.42 +	b = v3_sub(v2, v0);
   16.43 +	norm = v3_cross(a, b);
   16.44 +	norm = v3_normalize(norm);
   16.45 +
   16.46 +	return plane_ptnorm(v0, norm);
   16.47 +}
   16.48 +
   16.49 +plane_t plane_ptnorm(vec3_t pt, vec3_t normal)
   16.50 +{
   16.51 +	plane_t plane;
   16.52 +
   16.53 +	plane.norm = normal;
   16.54 +	plane.d = v3_dot(pt, normal);
   16.55 +
   16.56 +	return plane;
   16.57 +}
   16.58 +
   16.59 +plane_t plane_invert(plane_t p)
   16.60 +{
   16.61 +	p.norm = v3_neg(p.norm);
   16.62 +	p.d = -p.d;
   16.63 +	return p;
   16.64 +}
   16.65 +
   16.66 +scalar_t plane_signed_dist(plane_t plane, vec3_t pt)
   16.67 +{
   16.68 +	vec3_t pp = plane_point(plane);
   16.69 +	vec3_t pptopt = v3_sub(pt, pp);
   16.70 +	return v3_dot(pptopt, plane.norm);
   16.71 +}
   16.72 +
   16.73 +scalar_t plane_dist(plane_t plane, vec3_t pt)
   16.74 +{
   16.75 +	return fabs(plane_signed_dist(plane, pt));
   16.76 +}
   16.77 +
   16.78 +vec3_t plane_point(plane_t plane)
   16.79 +{
   16.80 +	return v3_scale(plane.norm, plane.d);
   16.81 +}
   16.82 +
   16.83 +int plane_ray_intersect(ray_t ray, plane_t plane, scalar_t *pos)
   16.84 +{
   16.85 +	vec3_t pt, orig_to_pt;
   16.86 +	scalar_t ndotdir;
   16.87 +
   16.88 +	pt = plane_point(plane);
   16.89 +	ndotdir = v3_dot(plane.norm, ray.dir);
   16.90 +
   16.91 +	if(fabs(ndotdir) < 1e-7) {
   16.92 +		return 0;
   16.93 +	}
   16.94 +
   16.95 +	if(pos) {
   16.96 +		orig_to_pt = v3_sub(pt, ray.origin);
   16.97 +		*pos = v3_dot(plane.norm, orig_to_pt) / ndotdir;
   16.98 +	}
   16.99 +	return 1;
  16.100 +}
  16.101 +
  16.102 +sphere_t sphere_cons(scalar_t x, scalar_t y, scalar_t z, scalar_t rad)
  16.103 +{
  16.104 +	sphere_t sph;
  16.105 +	sph.pos.x = x;
  16.106 +	sph.pos.y = y;
  16.107 +	sph.pos.z = z;
  16.108 +	sph.rad = rad;
  16.109 +	return sph;
  16.110 +}
  16.111 +
  16.112 +int sphere_ray_intersect(ray_t ray, sphere_t sph, scalar_t *pos)
  16.113 +{
  16.114 +	scalar_t a, b, c, d, sqrt_d, t1, t2, t;
  16.115 +
  16.116 +	a = v3_dot(ray.dir, ray.dir);
  16.117 +	b = 2.0 * ray.dir.x * (ray.origin.x - sph.pos.x) +
  16.118 +		2.0 * ray.dir.y * (ray.origin.y - sph.pos.y) +
  16.119 +		2.0 * ray.dir.z * (ray.origin.z - sph.pos.z);
  16.120 +	c = v3_dot(sph.pos, sph.pos) + v3_dot(ray.origin, ray.origin) +
  16.121 +		2.0 * v3_dot(v3_neg(sph.pos), ray.origin) - sph.rad * sph.rad;
  16.122 +
  16.123 +	d = b * b - 4.0 * a * c;
  16.124 +	if(d < 0.0) {
  16.125 +		return 0;
  16.126 +	}
  16.127 +
  16.128 +	sqrt_d = sqrt(d);
  16.129 +	t1 = (-b + sqrt_d) / (2.0 * a);
  16.130 +	t2 = (-b - sqrt_d) / (2.0 * a);
  16.131 +
  16.132 +	if(t1 < 1e-7 || t1 > 1.0) {
  16.133 +		t1 = t2;
  16.134 +	}
  16.135 +	if(t2 < 1e-7 || t2 > 1.0) {
  16.136 +		t2 = t1;
  16.137 +	}
  16.138 +	t = t1 < t2 ? t1 : t2;
  16.139 +
  16.140 +	if(t < 1e-7 || t > 1.0) {
  16.141 +		return 0;
  16.142 +	}
  16.143 +
  16.144 +	if(pos) {
  16.145 +		*pos = t;
  16.146 +	}
  16.147 +	return 1;
  16.148 +}
  16.149 +
  16.150 +int sphere_sphere_intersect(sphere_t sph1, sphere_t sph2, scalar_t *pos, scalar_t *rad)
  16.151 +{
  16.152 +	return -1;
  16.153 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/libs/vmath/geom.h	Sun Sep 29 08:20:19 2013 +0300
    17.3 @@ -0,0 +1,72 @@
    17.4 +/*
    17.5 +libvmath - a vector math library
    17.6 +Copyright (C) 2004-2012 John Tsiombikas <nuclear@member.fsf.org>
    17.7 +
    17.8 +This program is free software: you can redistribute it and/or modify
    17.9 +it under the terms of the GNU Lesser General Public License as published
   17.10 +by the Free Software Foundation, either version 3 of the License, or
   17.11 +(at your option) any later version.
   17.12 +
   17.13 +This program is distributed in the hope that it will be useful,
   17.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   17.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17.16 +GNU Lesser General Public License for more details.
   17.17 +
   17.18 +You should have received a copy of the GNU Lesser General Public License
   17.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
   17.20 +*/
   17.21 +#ifndef LIBVMATH_GEOM_H_
   17.22 +#define LIBVMATH_GEOM_H_
   17.23 +
   17.24 +#include "vector.h"
   17.25 +#include "ray.h"
   17.26 +
   17.27 +typedef struct {
   17.28 +	vec3_t norm;
   17.29 +	scalar_t d;
   17.30 +} plane_t;
   17.31 +
   17.32 +typedef struct {
   17.33 +	vec3_t pos;
   17.34 +	scalar_t rad;
   17.35 +} sphere_t;
   17.36 +
   17.37 +typedef struct {
   17.38 +	vec3_t min, max;
   17.39 +} aabox_t;
   17.40 +
   17.41 +#ifdef __cplusplus
   17.42 +extern "C" {
   17.43 +#endif
   17.44 +
   17.45 +/* planes are good... you need planes, yes you do */
   17.46 +plane_t plane_cons(scalar_t nx, scalar_t ny, scalar_t nz, scalar_t d);
   17.47 +plane_t plane_poly(vec3_t v0, vec3_t v1, vec3_t v2);
   17.48 +plane_t plane_ptnorm(vec3_t pt, vec3_t normal);
   17.49 +
   17.50 +plane_t plane_invert(plane_t p);
   17.51 +
   17.52 +scalar_t plane_signed_dist(plane_t plane, vec3_t pt);
   17.53 +scalar_t plane_dist(plane_t plane, vec3_t pt);
   17.54 +vec3_t plane_point(plane_t plane);
   17.55 +
   17.56 +int plane_ray_intersect(ray_t ray, plane_t plane, scalar_t *pos);
   17.57 +
   17.58 +/* spheres always come in handy */
   17.59 +sphere_t sphere_cons(scalar_t x, scalar_t y, scalar_t z, scalar_t rad);
   17.60 +
   17.61 +int sphere_ray_intersect(ray_t ray, sphere_t sph, scalar_t *pos);
   17.62 +int sphere_sphere_intersect(sphere_t sph1, sphere_t sph2, scalar_t *pos, scalar_t *rad);
   17.63 +
   17.64 +#ifdef __cplusplus
   17.65 +}
   17.66 +
   17.67 +/* TODO
   17.68 +class Plane : public plane_t {
   17.69 +public:
   17.70 +};
   17.71 +*/
   17.72 +
   17.73 +#endif
   17.74 +
   17.75 +#endif	/* LIBVMATH_GEOM_H_ */
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/libs/vmath/matrix.cc	Sun Sep 29 08:20:19 2013 +0300
    18.3 @@ -0,0 +1,821 @@
    18.4 +#include <cstdio>
    18.5 +#include <cmath>
    18.6 +#include "matrix.h"
    18.7 +#include "vector.h"
    18.8 +#include "quat.h"
    18.9 +
   18.10 +using namespace std;
   18.11 +
   18.12 +// ----------- Matrix3x3 --------------
   18.13 +
   18.14 +Matrix3x3 Matrix3x3::identity = Matrix3x3(1, 0, 0, 0, 1, 0, 0, 0, 1);
   18.15 +
   18.16 +Matrix3x3::Matrix3x3()
   18.17 +{
   18.18 +	*this = Matrix3x3(1, 0, 0, 0, 1, 0, 0, 0, 1);
   18.19 +}
   18.20 +
   18.21 +Matrix3x3::Matrix3x3(	scalar_t m11, scalar_t m12, scalar_t m13,
   18.22 +						scalar_t m21, scalar_t m22, scalar_t m23,
   18.23 +						scalar_t m31, scalar_t m32, scalar_t m33)
   18.24 +{
   18.25 +	m[0][0] = m11; m[0][1] = m12; m[0][2] = m13;
   18.26 +	m[1][0] = m21; m[1][1] = m22; m[1][2] = m23;
   18.27 +	m[2][0] = m31; m[2][1] = m32; m[2][2] = m33;
   18.28 +}
   18.29 +
   18.30 +Matrix3x3::Matrix3x3(const Vector3 &ivec, const Vector3 &jvec, const Vector3 &kvec)
   18.31 +{
   18.32 +	set_row_vector(ivec, 0);
   18.33 +	set_row_vector(jvec, 1);
   18.34 +	set_row_vector(kvec, 2);
   18.35 +}
   18.36 +
   18.37 +Matrix3x3::Matrix3x3(const mat3_t cmat)
   18.38 +{
   18.39 +	memcpy(m, cmat, sizeof(mat3_t));
   18.40 +}
   18.41 +
   18.42 +Matrix3x3::Matrix3x3(const Matrix4x4 &mat4x4)
   18.43 +{
   18.44 +	for(int i=0; i<3; i++) {
   18.45 +		for(int j=0; j<3; j++) {
   18.46 +			m[i][j] = mat4x4[i][j];
   18.47 +		}
   18.48 +	}
   18.49 +}
   18.50 +
   18.51 +Matrix3x3 operator +(const Matrix3x3 &m1, const Matrix3x3 &m2)
   18.52 +{
   18.53 +	Matrix3x3 res;
   18.54 +	const scalar_t *op1 = m1.m[0], *op2 = m2.m[0];
   18.55 +	scalar_t *dest = res.m[0];
   18.56 +
   18.57 +	for(int i=0; i<9; i++) {
   18.58 +		*dest++ = *op1++ + *op2++;
   18.59 +	}
   18.60 +	return res;
   18.61 +}
   18.62 +
   18.63 +Matrix3x3 operator -(const Matrix3x3 &m1, const Matrix3x3 &m2)
   18.64 +{
   18.65 +	Matrix3x3 res;
   18.66 +	const scalar_t *op1 = m1.m[0], *op2 = m2.m[0];
   18.67 +	scalar_t *dest = res.m[0];
   18.68 +
   18.69 +	for(int i=0; i<9; i++) {
   18.70 +		*dest++ = *op1++ - *op2++;
   18.71 +	}
   18.72 +	return res;
   18.73 +}
   18.74 +
   18.75 +Matrix3x3 operator *(const Matrix3x3 &m1, const Matrix3x3 &m2)
   18.76 +{
   18.77 +	Matrix3x3 res;
   18.78 +	for(int i=0; i<3; i++) {
   18.79 +		for(int j=0; j<3; j++) {
   18.80 +			res.m[i][j] = m1.m[i][0] * m2.m[0][j] + m1.m[i][1] * m2.m[1][j] + m1.m[i][2] * m2.m[2][j];
   18.81 +		}
   18.82 +	}
   18.83 +	return res;
   18.84 +}
   18.85 +
   18.86 +void operator +=(Matrix3x3 &m1, const Matrix3x3 &m2)
   18.87 +{
   18.88 +	scalar_t *op1 = m1.m[0];
   18.89 +	const scalar_t *op2 = m2.m[0];
   18.90 +
   18.91 +	for(int i=0; i<9; i++) {
   18.92 +		*op1++ += *op2++;
   18.93 +	}
   18.94 +}
   18.95 +
   18.96 +void operator -=(Matrix3x3 &m1, const Matrix3x3 &m2)
   18.97 +{
   18.98 +	scalar_t *op1 = m1.m[0];
   18.99 +	const scalar_t *op2 = m2.m[0];
  18.100 +
  18.101 +	for(int i=0; i<9; i++) {
  18.102 +		*op1++ -= *op2++;
  18.103 +	}
  18.104 +}
  18.105 +
  18.106 +void operator *=(Matrix3x3 &m1, const Matrix3x3 &m2)
  18.107 +{
  18.108 +	Matrix3x3 res;
  18.109 +	for(int i=0; i<3; i++) {
  18.110 +		for(int j=0; j<3; j++) {
  18.111 +			res.m[i][j] = m1.m[i][0] * m2.m[0][j] + m1.m[i][1] * m2.m[1][j] + m1.m[i][2] * m2.m[2][j];
  18.112 +		}
  18.113 +	}
  18.114 +	memcpy(m1.m, res.m, 9 * sizeof(scalar_t));
  18.115 +}
  18.116 +
  18.117 +Matrix3x3 operator *(const Matrix3x3 &mat, scalar_t scalar)
  18.118 +{
  18.119 +	Matrix3x3 res;
  18.120 +	const scalar_t *mptr = mat.m[0];
  18.121 +	scalar_t *dptr = res.m[0];
  18.122 +
  18.123 +	for(int i=0; i<9; i++) {
  18.124 +		*dptr++ = *mptr++ * scalar;
  18.125 +	}
  18.126 +	return res;
  18.127 +}
  18.128 +
  18.129 +Matrix3x3 operator *(scalar_t scalar, const Matrix3x3 &mat)
  18.130 +{
  18.131 +	Matrix3x3 res;
  18.132 +	const scalar_t *mptr = mat.m[0];
  18.133 +	scalar_t *dptr = res.m[0];
  18.134 +
  18.135 +	for(int i=0; i<9; i++) {
  18.136 +		*dptr++ = *mptr++ * scalar;
  18.137 +	}
  18.138 +	return res;
  18.139 +}
  18.140 +
  18.141 +void operator *=(Matrix3x3 &mat, scalar_t scalar)
  18.142 +{
  18.143 +	scalar_t *mptr = mat.m[0];
  18.144 +
  18.145 +	for(int i=0; i<9; i++) {
  18.146 +		*mptr++ *= scalar;
  18.147 +	}
  18.148 +}
  18.149 +
  18.150 +void Matrix3x3::translate(const Vector2 &trans)
  18.151 +{
  18.152 +	Matrix3x3 tmat(1, 0, trans.x, 0, 1, trans.y, 0, 0, 1);
  18.153 +	*this *= tmat;
  18.154 +}
  18.155 +
  18.156 +void Matrix3x3::set_translation(const Vector2 &trans)
  18.157 +{
  18.158 +	*this = Matrix3x3(1, 0, trans.x, 0, 1, trans.y, 0, 0, 1);
  18.159 +}
  18.160 +
  18.161 +void Matrix3x3::rotate(scalar_t angle)
  18.162 +{
  18.163 +	scalar_t cos_a = cos(angle);
  18.164 +	scalar_t sin_a = sin(angle);
  18.165 +	Matrix3x3 rmat(	cos_a,	-sin_a,		0,
  18.166 +					sin_a,	cos_a,		0,
  18.167 +					0,		0,			1);
  18.168 +	*this *= rmat;
  18.169 +}
  18.170 +
  18.171 +void Matrix3x3::set_rotation(scalar_t angle)
  18.172 +{
  18.173 +	scalar_t cos_a = cos(angle);
  18.174 +	scalar_t sin_a = sin(angle);
  18.175 +	*this = Matrix3x3(cos_a, -sin_a, 0, sin_a, cos_a, 0, 0, 0, 1);
  18.176 +}
  18.177 +
  18.178 +void Matrix3x3::rotate(const Vector3 &euler_angles)
  18.179 +{
  18.180 +	Matrix3x3 xrot, yrot, zrot;
  18.181 +
  18.182 +	xrot = Matrix3x3(	1,			0,					0,
  18.183 +						0,	cos(euler_angles.x),	-sin(euler_angles.x),
  18.184 +						0,	sin(euler_angles.x),	cos(euler_angles.x));
  18.185 +
  18.186 +	yrot = Matrix3x3(	cos(euler_angles.y),	0,	sin(euler_angles.y),
  18.187 +								0,				1,				0,
  18.188 +						-sin(euler_angles.y),	0,	cos(euler_angles.y));
  18.189 +
  18.190 +	zrot = Matrix3x3(	cos(euler_angles.z),	-sin(euler_angles.z),	0,
  18.191 +						sin(euler_angles.z),	cos(euler_angles.z),	0,
  18.192 +								0,						0,				1);
  18.193 +
  18.194 +	*this *= xrot * yrot * zrot;
  18.195 +}
  18.196 +
  18.197 +void Matrix3x3::set_rotation(const Vector3 &euler_angles)
  18.198 +{
  18.199 +	Matrix3x3 xrot, yrot, zrot;
  18.200 +
  18.201 +	xrot = Matrix3x3(	1,			0,					0,
  18.202 +						0,	cos(euler_angles.x),	-sin(euler_angles.x),
  18.203 +						0,	sin(euler_angles.x),	cos(euler_angles.x));
  18.204 +
  18.205 +	yrot = Matrix3x3(	cos(euler_angles.y),	0,	sin(euler_angles.y),
  18.206 +								0,				1,				0,
  18.207 +						-sin(euler_angles.y),	0,	cos(euler_angles.y));
  18.208 +
  18.209 +	zrot = Matrix3x3(	cos(euler_angles.z),	-sin(euler_angles.z),	0,
  18.210 +						sin(euler_angles.z),	cos(euler_angles.z),	0,
  18.211 +								0,						0,				1);
  18.212 +
  18.213 +	*this = xrot * yrot * zrot;
  18.214 +}
  18.215 +
  18.216 +void Matrix3x3::rotate(const Vector3 &axis, scalar_t angle)
  18.217 +{
  18.218 +	scalar_t sina = (scalar_t)sin(angle);
  18.219 +	scalar_t cosa = (scalar_t)cos(angle);
  18.220 +	scalar_t invcosa = 1-cosa;
  18.221 +	scalar_t nxsq = axis.x * axis.x;
  18.222 +	scalar_t nysq = axis.y * axis.y;
  18.223 +	scalar_t nzsq = axis.z * axis.z;
  18.224 +
  18.225 +	Matrix3x3 xform;
  18.226 +	xform.m[0][0] = nxsq + (1-nxsq) * cosa;
  18.227 +	xform.m[0][1] = axis.x * axis.y * invcosa - axis.z * sina;
  18.228 +	xform.m[0][2] = axis.x * axis.z * invcosa + axis.y * sina;
  18.229 +
  18.230 +	xform.m[1][0] = axis.x * axis.y * invcosa + axis.z * sina;
  18.231 +	xform.m[1][1] = nysq + (1-nysq) * cosa;
  18.232 +	xform.m[1][2] = axis.y * axis.z * invcosa - axis.x * sina;
  18.233 +
  18.234 +	xform.m[2][0] = axis.x * axis.z * invcosa - axis.y * sina;
  18.235 +	xform.m[2][1] = axis.y * axis.z * invcosa + axis.x * sina;
  18.236 +	xform.m[2][2] = nzsq + (1-nzsq) * cosa;
  18.237 +
  18.238 +	*this *= xform;
  18.239 +}
  18.240 +
  18.241 +void Matrix3x3::set_rotation(const Vector3 &axis, scalar_t angle)
  18.242 +{
  18.243 +	scalar_t sina = (scalar_t)sin(angle);
  18.244 +	scalar_t cosa = (scalar_t)cos(angle);
  18.245 +	scalar_t invcosa = 1-cosa;
  18.246 +	scalar_t nxsq = axis.x * axis.x;
  18.247 +	scalar_t nysq = axis.y * axis.y;
  18.248 +	scalar_t nzsq = axis.z * axis.z;
  18.249 +
  18.250 +	reset_identity();
  18.251 +	m[0][0] = nxsq + (1-nxsq) * cosa;
  18.252 +	m[0][1] = axis.x * axis.y * invcosa - axis.z * sina;
  18.253 +	m[0][2] = axis.x * axis.z * invcosa + axis.y * sina;
  18.254 +	m[1][0] = axis.x * axis.y * invcosa + axis.z * sina;
  18.255 +	m[1][1] = nysq + (1-nysq) * cosa;
  18.256 +	m[1][2] = axis.y * axis.z * invcosa - axis.x * sina;
  18.257 +	m[2][0] = axis.x * axis.z * invcosa - axis.y * sina;
  18.258 +	m[2][1] = axis.y * axis.z * invcosa + axis.x * sina;
  18.259 +	m[2][2] = nzsq + (1-nzsq) * cosa;
  18.260 +}
  18.261 +
  18.262 +// Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
  18.263 +// article "Quaternion Calculus and Fast Animation".
  18.264 +// adapted from: http://www.geometrictools.com/LibMathematics/Algebra/Wm5Quaternion.inl
  18.265 +Quaternion Matrix3x3::get_rotation_quat() const
  18.266 +{
  18.267 +	static const int next[3] = {1, 2, 0};
  18.268 +
  18.269 +	float quat[4];
  18.270 +
  18.271 +	scalar_t trace = m[0][0] + m[1][1] + m[2][2];
  18.272 +	scalar_t root;
  18.273 +
  18.274 +	if(trace > 0.0f) {
  18.275 +		// |w| > 1/2
  18.276 +		root = sqrt(trace + 1.0f);	// 2w
  18.277 +		quat[0] = 0.5f * root;
  18.278 +		root = 0.5f / root;	// 1 / 4w
  18.279 +		quat[1] = (m[2][1] - m[1][2]) * root;
  18.280 +		quat[2] = (m[0][2] - m[2][0]) * root;
  18.281 +		quat[3] = (m[1][0] - m[0][1]) * root;
  18.282 +	} else {
  18.283 +		// |w| <= 1/2
  18.284 +		int i = 0;
  18.285 +		if(m[1][1] > m[0][0]) {
  18.286 +			i = 1;
  18.287 +		}
  18.288 +		if(m[2][2] > m[i][i]) {
  18.289 +			i = 2;
  18.290 +		}
  18.291 +		int j = next[i];
  18.292 +		int k = next[j];
  18.293 +
  18.294 +		root = sqrt(m[i][i] - m[j][j] - m[k][k] + 1.0f);
  18.295 +		quat[i + 1] = 0.5f * root;
  18.296 +		root = 0.5f / root;
  18.297 +		quat[0] = (m[k][j] - m[j][k]) * root;
  18.298 +		quat[j + 1] = (m[j][i] - m[i][j]) * root;
  18.299 +		quat[k + 1] = (m[k][i] - m[i][k]) * root;
  18.300 +	}
  18.301 +	return Quaternion(quat[0], quat[1], quat[2], quat[3]);
  18.302 +}
  18.303 +
  18.304 +void Matrix3x3::scale(const Vector3 &scale_vec)
  18.305 +{
  18.306 +	Matrix3x3 smat(	scale_vec.x, 0, 0,
  18.307 +					0, scale_vec.y, 0,
  18.308 +					0, 0, scale_vec.z);
  18.309 +	*this *= smat;
  18.310 +}
  18.311 +
  18.312 +void Matrix3x3::set_scaling(const Vector3 &scale_vec)
  18.313 +{
  18.314 +	*this = Matrix3x3(	scale_vec.x, 0, 0,
  18.315 +						0, scale_vec.y, 0,
  18.316 +						0, 0, scale_vec.z);
  18.317 +}
  18.318 +
  18.319 +void Matrix3x3::set_column_vector(const Vector3 &vec, unsigned int col_index)
  18.320 +{
  18.321 +	m[0][col_index] = vec.x;
  18.322 +	m[1][col_index] = vec.y;
  18.323 +	m[2][col_index] = vec.z;
  18.324 +}
  18.325 +
  18.326 +void Matrix3x3::set_row_vector(const Vector3 &vec, unsigned int row_index)
  18.327 +{
  18.328 +	m[row_index][0] = vec.x;
  18.329 +	m[row_index][1] = vec.y;
  18.330 +	m[row_index][2] = vec.z;
  18.331 +}
  18.332 +
  18.333 +Vector3 Matrix3x3::get_column_vector(unsigned int col_index) const
  18.334 +{
  18.335 +	return Vector3(m[0][col_index], m[1][col_index], m[2][col_index]);
  18.336 +}
  18.337 +
  18.338 +Vector3 Matrix3x3::get_row_vector(unsigned int row_index) const
  18.339 +{
  18.340 +	return Vector3(m[row_index][0], m[row_index][1], m[row_index][2]);
  18.341 +}
  18.342 +
  18.343 +void Matrix3x3::transpose()
  18.344 +{
  18.345 +	Matrix3x3 tmp = *this;
  18.346 +	for(int i=0; i<3; i++) {
  18.347 +		for(int j=0; j<3; j++) {
  18.348 +			m[i][j] = tmp[j][i];
  18.349 +		}
  18.350 +	}
  18.351 +}
  18.352 +
  18.353 +Matrix3x3 Matrix3x3::transposed() const
  18.354 +{
  18.355 +	Matrix3x3 res;
  18.356 +	for(int i=0; i<3; i++) {
  18.357 +		for(int j=0; j<3; j++) {
  18.358 +			res[i][j] = m[j][i];
  18.359 +		}
  18.360 +	}
  18.361 +	return res;
  18.362 +}
  18.363 +
  18.364 +scalar_t Matrix3x3::determinant() const
  18.365 +{
  18.366 +	return	m[0][0] * (m[1][1]*m[2][2] - m[1][2]*m[2][1]) -
  18.367 +			m[0][1] * (m[1][0]*m[2][2] - m[1][2]*m[2][0]) +
  18.368 +			m[0][2] * (m[1][0]*m[2][1] - m[1][1]*m[2][0]);
  18.369 +}
  18.370 +
  18.371 +Matrix3x3 Matrix3x3::inverse() const
  18.372 +{
  18.373 +	// TODO: implement 3x3 inverse
  18.374 +	return *this;
  18.375 +}
  18.376 +
  18.377 +ostream &operator <<(ostream &out, const Matrix3x3 &mat)
  18.378 +{
  18.379 +	for(int i=0; i<3; i++) {
  18.380 +		char str[100];
  18.381 +		sprintf(str, "[ %12.5f %12.5f %12.5f ]\n", (float)mat.m[i][0], (float)mat.m[i][1], (float)mat.m[i][2]);
  18.382 +		out << str;
  18.383 +	}
  18.384 +	return out;
  18.385 +}
  18.386 +
  18.387 +
  18.388 +
  18.389 +/* ----------------- Matrix4x4 implementation --------------- */
  18.390 +
  18.391 +Matrix4x4 Matrix4x4::identity = Matrix4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
  18.392 +
  18.393 +Matrix4x4::Matrix4x4()
  18.394 +{
  18.395 +	*this = Matrix4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
  18.396 +}
  18.397 +
  18.398 +Matrix4x4::Matrix4x4(	scalar_t m11, scalar_t m12, scalar_t m13, scalar_t m14,
  18.399 +						scalar_t m21, scalar_t m22, scalar_t m23, scalar_t m24,
  18.400 +						scalar_t m31, scalar_t m32, scalar_t m33, scalar_t m34,
  18.401 +						scalar_t m41, scalar_t m42, scalar_t m43, scalar_t m44)
  18.402 +{
  18.403 +	m[0][0] = m11; m[0][1] = m12; m[0][2] = m13; m[0][3] = m14;
  18.404 +	m[1][0] = m21; m[1][1] = m22; m[1][2] = m23; m[1][3] = m24;
  18.405 +	m[2][0] = m31; m[2][1] = m32; m[2][2] = m33; m[2][3] = m34;
  18.406 +	m[3][0] = m41; m[3][1] = m42; m[3][2] = m43; m[3][3] = m44;
  18.407 +}
  18.408 +
  18.409 +Matrix4x4::Matrix4x4(const mat4_t cmat)
  18.410 +{
  18.411 +	memcpy(m, cmat, sizeof(mat4_t));
  18.412 +}
  18.413 +
  18.414 +Matrix4x4::Matrix4x4(const Matrix3x3 &mat3x3)
  18.415 +{
  18.416 +	reset_identity();
  18.417 +	for(int i=0; i<3; i++) {
  18.418 +		for(int j=0; j<3; j++) {
  18.419 +			m[i][j] = mat3x3[i][j];
  18.420 +		}
  18.421 +	}
  18.422 +}
  18.423 +
  18.424 +Matrix4x4 operator +(const Matrix4x4 &m1, const Matrix4x4 &m2)
  18.425 +{
  18.426 +	Matrix4x4 res;
  18.427 +	const scalar_t *op1 = m1.m[0], *op2 = m2.m[0];
  18.428 +	scalar_t *dest = res.m[0];
  18.429 +
  18.430 +	for(int i=0; i<16; i++) {
  18.431 +		*dest++ = *op1++ + *op2++;
  18.432 +	}
  18.433 +	return res;
  18.434 +}
  18.435 +
  18.436 +Matrix4x4 operator -(const Matrix4x4 &m1, const Matrix4x4 &m2)
  18.437 +{
  18.438 +	Matrix4x4 res;
  18.439 +	const scalar_t *op1 = m1.m[0], *op2 = m2.m[0];
  18.440 +	scalar_t *dest = res.m[0];
  18.441 +
  18.442 +	for(int i=0; i<16; i++) {
  18.443 +		*dest++ = *op1++ - *op2++;
  18.444 +	}
  18.445 +	return res;
  18.446 +}
  18.447 +
  18.448 +void operator +=(Matrix4x4 &m1, const Matrix4x4 &m2)
  18.449 +{
  18.450 +	scalar_t *op1 = m1.m[0];
  18.451 +	const scalar_t *op2 = m2.m[0];
  18.452 +
  18.453 +	for(int i=0; i<16; i++) {
  18.454 +		*op1++ += *op2++;
  18.455 +	}
  18.456 +}
  18.457 +
  18.458 +void operator -=(Matrix4x4 &m1, const Matrix4x4 &m2)
  18.459 +{
  18.460 +	scalar_t *op1 = m1.m[0];
  18.461 +	const scalar_t *op2 = m2.m[0];
  18.462 +
  18.463 +	for(int i=0; i<16; i++) {
  18.464 +		*op1++ -= *op2++;
  18.465 +	}
  18.466 +}
  18.467 +
  18.468 +Matrix4x4 operator *(const Matrix4x4 &mat, scalar_t scalar)
  18.469 +{
  18.470 +	Matrix4x4 res;
  18.471 +	const scalar_t *mptr = mat.m[0];
  18.472 +	scalar_t *dptr = res.m[0];
  18.473 +
  18.474 +	for(int i=0; i<16; i++) {
  18.475 +		*dptr++ = *mptr++ * scalar;
  18.476 +	}
  18.477 +	return res;
  18.478 +}
  18.479 +
  18.480 +Matrix4x4 operator *(scalar_t scalar, const Matrix4x4 &mat)
  18.481 +{
  18.482 +	Matrix4x4 res;
  18.483 +	const scalar_t *mptr = mat.m[0];
  18.484 +	scalar_t *dptr = res.m[0];
  18.485 +
  18.486 +	for(int i=0; i<16; i++) {
  18.487 +		*dptr++ = *mptr++ * scalar;
  18.488 +	}
  18.489 +	return res;
  18.490 +}
  18.491 +
  18.492 +void operator *=(Matrix4x4 &mat, scalar_t scalar)
  18.493 +{
  18.494 +	scalar_t *mptr = mat.m[0];
  18.495 +
  18.496 +	for(int i=0; i<16; i++) {
  18.497 +		*mptr++ *= scalar;
  18.498 +	}
  18.499 +}
  18.500 +
  18.501 +void Matrix4x4::translate(const Vector3 &trans)
  18.502 +{
  18.503 +	Matrix4x4 tmat(1, 0, 0, trans.x, 0, 1, 0, trans.y, 0, 0, 1, trans.z, 0, 0, 0, 1);
  18.504 +	*this *= tmat;
  18.505 +}
  18.506 +
  18.507 +void Matrix4x4::set_translation(const Vector3 &trans)
  18.508 +{
  18.509 +	*this = Matrix4x4(1, 0, 0, trans.x, 0, 1, 0, trans.y, 0, 0, 1, trans.z, 0, 0, 0, 1);
  18.510 +}
  18.511 +
  18.512 +Vector3 Matrix4x4::get_translation() const
  18.513 +{
  18.514 +	return Vector3(m[0][3], m[1][3], m[2][3]);
  18.515 +}
  18.516 +
  18.517 +void Matrix4x4::rotate(const Vector3 &euler_angles)
  18.518 +{
  18.519 +	Matrix3x3 xrot, yrot, zrot;
  18.520 +
  18.521 +	xrot = Matrix3x3(	1,			0,					0,
  18.522 +						0,	cos(euler_angles.x),	-sin(euler_angles.x),
  18.523 +						0,	sin(euler_angles.x),	cos(euler_angles.x));
  18.524 +
  18.525 +	yrot = Matrix3x3(	cos(euler_angles.y),	0,	sin(euler_angles.y),
  18.526 +								0,				1,				0,
  18.527 +						-sin(euler_angles.y),	0,	cos(euler_angles.y));
  18.528 +
  18.529 +	zrot = Matrix3x3(	cos(euler_angles.z),	-sin(euler_angles.z),	0,
  18.530 +						sin(euler_angles.z),	cos(euler_angles.z),	0,
  18.531 +								0,						0,				1);
  18.532 +
  18.533 +	*this *= Matrix4x4(xrot * yrot * zrot);
  18.534 +}
  18.535 +
  18.536 +void Matrix4x4::set_rotation(const Vector3 &euler_angles)
  18.537 +{
  18.538 +	Matrix3x3 xrot, yrot, zrot;
  18.539 +
  18.540 +	xrot = Matrix3x3(	1,			0,					0,
  18.541 +						0,	cos(euler_angles.x),	-sin(euler_angles.x),
  18.542 +						0,	sin(euler_angles.x),	cos(euler_angles.x));
  18.543 +
  18.544 +	yrot = Matrix3x3(	cos(euler_angles.y),	0,	sin(euler_angles.y),
  18.545 +								0,				1,				0,
  18.546 +						-sin(euler_angles.y),	0,	cos(euler_angles.y));
  18.547 +
  18.548 +	zrot = Matrix3x3(	cos(euler_angles.z),	-sin(euler_angles.z),	0,
  18.549 +						sin(euler_angles.z),	cos(euler_angles.z),	0,
  18.550 +								0,						0,				1);
  18.551 +
  18.552 +	*this = Matrix4x4(xrot * yrot * zrot);
  18.553 +}
  18.554 +
  18.555 +void Matrix4x4::rotate(const Vector3 &axis, scalar_t angle)
  18.556 +{
  18.557 +	scalar_t sina = (scalar_t)sin(angle);
  18.558 +	scalar_t cosa = (scalar_t)cos(angle);
  18.559 +	scalar_t invcosa = 1-cosa;
  18.560 +	scalar_t nxsq = axis.x * axis.x;
  18.561 +	scalar_t nysq = axis.y * axis.y;
  18.562 +	scalar_t nzsq = axis.z * axis.z;
  18.563 +
  18.564 +	Matrix4x4 xform;
  18.565 +	xform[0][0] = nxsq + (1-nxsq) * cosa;
  18.566 +	xform[0][1] = axis.x * axis.y * invcosa - axis.z * sina;
  18.567 +	xform[0][2] = axis.x * axis.z * invcosa + axis.y * sina;
  18.568 +	xform[1][0] = axis.x * axis.y * invcosa + axis.z * sina;
  18.569 +	xform[1][1] = nysq + (1-nysq) * cosa;
  18.570 +	xform[1][2] = axis.y * axis.z * invcosa - axis.x * sina;
  18.571 +	xform[2][0] = axis.x * axis.z * invcosa - axis.y * sina;
  18.572 +	xform[2][1] = axis.y * axis.z * invcosa + axis.x * sina;
  18.573 +	xform[2][2] = nzsq + (1-nzsq) * cosa;
  18.574 +
  18.575 +	*this *= xform;
  18.576 +}
  18.577 +
  18.578 +void Matrix4x4::set_rotation(const Vector3 &axis, scalar_t angle)
  18.579 +{
  18.580 +	scalar_t sina = (scalar_t)sin(angle);
  18.581 +	scalar_t cosa = (scalar_t)cos(angle);
  18.582 +	scalar_t invcosa = 1-cosa;
  18.583 +	scalar_t nxsq = axis.x * axis.x;
  18.584 +	scalar_t nysq = axis.y * axis.y;
  18.585 +	scalar_t nzsq = axis.z * axis.z;
  18.586 +
  18.587 +	reset_identity();
  18.588 +	m[0][0] = nxsq + (1-nxsq) * cosa;
  18.589 +	m[0][1] = axis.x * axis.y * invcosa - axis.z * sina;
  18.590 +	m[0][2] = axis.x * axis.z * invcosa + axis.y * sina;
  18.591 +	m[1][0] = axis.x * axis.y * invcosa + axis.z * sina;
  18.592 +	m[1][1] = nysq + (1-nysq) * cosa;
  18.593 +	m[1][2] = axis.y * axis.z * invcosa - axis.x * sina;
  18.594 +	m[2][0] = axis.x * axis.z * invcosa - axis.y * sina;
  18.595 +	m[2][1] = axis.y * axis.z * invcosa + axis.x * sina;
  18.596 +	m[2][2] = nzsq + (1-nzsq) * cosa;
  18.597 +}
  18.598 +
  18.599 +void Matrix4x4::rotate(const Quaternion &quat)
  18.600 +{
  18.601 +	*this *= quat.get_rotation_matrix();
  18.602 +}
  18.603 +
  18.604 +void Matrix4x4::set_rotation(const Quaternion &quat)
  18.605 +{
  18.606 +	*this = quat.get_rotation_matrix();
  18.607 +}
  18.608 +
  18.609 +Quaternion Matrix4x4::get_rotation_quat() const
  18.610 +{
  18.611 +	Matrix3x3 mat3 = *this;
  18.612 +	return mat3.get_rotation_quat();
  18.613 +}
  18.614 +
  18.615 +void Matrix4x4::scale(const Vector4 &scale_vec)
  18.616 +{
  18.617 +	Matrix4x4 smat(	scale_vec.x, 0, 0, 0,
  18.618 +					0, scale_vec.y, 0, 0,
  18.619 +					0, 0, scale_vec.z, 0,
  18.620 +					0, 0, 0, scale_vec.w);
  18.621 +	*this *= smat;
  18.622 +}
  18.623 +
  18.624 +void Matrix4x4::set_scaling(const Vector4 &scale_vec)
  18.625 +{
  18.626 +	*this = Matrix4x4(	scale_vec.x, 0, 0, 0,
  18.627 +						0, scale_vec.y, 0, 0,
  18.628 +						0, 0, scale_vec.z, 0,
  18.629 +						0, 0, 0, scale_vec.w);
  18.630 +}
  18.631 +
  18.632 +Vector3 Matrix4x4::get_scaling() const
  18.633 +{
  18.634 +	Vector3 vi = get_row_vector(0);
  18.635 +	Vector3 vj = get_row_vector(1);
  18.636 +	Vector3 vk = get_row_vector(2);
  18.637 +
  18.638 +	return Vector3(vi.length(), vj.length(), vk.length());
  18.639 +}
  18.640 +
  18.641 +void Matrix4x4::set_perspective(float vfov, float aspect, float znear, float zfar)
  18.642 +{
  18.643 +	float f = 1.0f / tan(vfov * 0.5f);
  18.644 +    float dz = znear - zfar;
  18.645 +
  18.646 +	reset_identity();
  18.647 +
  18.648 +	m[0][0] = f / aspect;
  18.649 +    m[1][1] = f;
  18.650 +    m[2][2] = (zfar + znear) / dz;
  18.651 +    m[3][2] = -1.0f;
  18.652 +    m[2][3] = 2.0f * zfar * znear / dz;
  18.653 +    m[3][3] = 0.0f;
  18.654 +}
  18.655 +
  18.656 +void Matrix4x4::set_orthographic(float left, float right, float bottom, float top, float znear, float zfar)
  18.657 +{
  18.658 +	float dx = right - left;
  18.659 +	float dy = top - bottom;
  18.660 +	float dz = zfar - znear;
  18.661 +
  18.662 +	reset_identity();
  18.663 +
  18.664 +	m[0][0] = 2.0 / dx;
  18.665 +	m[1][1] = 2.0 / dy;
  18.666 +	m[2][2] = -2.0 / dz;
  18.667 +	m[0][3] = -(right + left) / dx;
  18.668 +	m[1][3] = -(top + bottom) / dy;
  18.669 +	m[2][3] = -(zfar + znear) / dz;
  18.670 +}
  18.671 +
  18.672 +void Matrix4x4::set_column_vector(const Vector4 &vec, unsigned int col_index)
  18.673 +{
  18.674 +	m[0][col_index] = vec.x;
  18.675 +	m[1][col_index] = vec.y;
  18.676 +	m[2][col_index] = vec.z;
  18.677 +	m[3][col_index] = vec.w;
  18.678 +}
  18.679 +
  18.680 +void Matrix4x4::set_row_vector(const Vector4 &vec, unsigned int row_index)
  18.681 +{
  18.682 +	m[row_index][0] = vec.x;
  18.683 +	m[row_index][1] = vec.y;
  18.684 +	m[row_index][2] = vec.z;
  18.685 +	m[row_index][3] = vec.w;
  18.686 +}
  18.687 +
  18.688 +Vector4 Matrix4x4::get_column_vector(unsigned int col_index) const
  18.689 +{
  18.690 +	return Vector4(m[0][col_index], m[1][col_index], m[2][col_index], m[3][col_index]);
  18.691 +}
  18.692 +
  18.693 +Vector4 Matrix4x4::get_row_vector(unsigned int row_index) const
  18.694 +{
  18.695 +	return Vector4(m[row_index][0], m[row_index][1], m[row_index][2], m[row_index][3]);
  18.696 +}
  18.697 +
  18.698 +void Matrix4x4::transpose()
  18.699 +{
  18.700 +	Matrix4x4 tmp = *this;
  18.701 +	for(int i=0; i<4; i++) {
  18.702 +		for(int j=0; j<4; j++) {
  18.703 +			m[i][j] = tmp[j][i];
  18.704 +		}
  18.705 +	}
  18.706 +}
  18.707 +
  18.708 +Matrix4x4 Matrix4x4::transposed() const
  18.709 +{
  18.710 +	Matrix4x4 res;
  18.711 +	for(int i=0; i<4; i++) {
  18.712 +		for(int j=0; j<4; j++) {
  18.713 +			res[i][j] = m[j][i];
  18.714 +		}
  18.715 +	}
  18.716 +	return res;
  18.717 +}
  18.718 +
  18.719 +scalar_t Matrix4x4::determinant() const
  18.720 +{
  18.721 +	scalar_t det11 =	(m[1][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
  18.722 +						(m[1][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) +
  18.723 +						(m[1][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2]));
  18.724 +
  18.725 +	scalar_t det12 =	(m[1][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
  18.726 +						(m[1][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
  18.727 +						(m[1][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2]));
  18.728 +
  18.729 +	scalar_t det13 =	(m[1][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) -
  18.730 +						(m[1][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
  18.731 +						(m[1][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
  18.732 +
  18.733 +	scalar_t det14 =	(m[1][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) -
  18.734 +						(m[1][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) +
  18.735 +						(m[1][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
  18.736 +
  18.737 +	return m[0][0] * det11 - m[0][1] * det12 + m[0][2] * det13 - m[0][3] * det14;
  18.738 +}
  18.739 +
  18.740 +
  18.741 +Matrix4x4 Matrix4x4::adjoint() const
  18.742 +{
  18.743 +	Matrix4x4 coef;
  18.744 +
  18.745 +	coef.m[0][0] =	(m[1][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
  18.746 +					(m[1][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) +
  18.747 +					(m[1][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2]));
  18.748 +	coef.m[0][1] =	(m[1][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
  18.749 +					(m[1][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
  18.750 +					(m[1][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2]));
  18.751 +	coef.m[0][2] =	(m[1][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) -
  18.752 +					(m[1][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
  18.753 +					(m[1][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
  18.754 +	coef.m[0][3] =	(m[1][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) -
  18.755 +					(m[1][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) +
  18.756 +					(m[1][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
  18.757 +
  18.758 +	coef.m[1][0] =	(m[0][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
  18.759 +					(m[0][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) +
  18.760 +					(m[0][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2]));
  18.761 +	coef.m[1][1] =	(m[0][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
  18.762 +					(m[0][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
  18.763 +					(m[0][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2]));
  18.764 +	coef.m[1][2] =	(m[0][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) -
  18.765 +					(m[0][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
  18.766 +					(m[0][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
  18.767 +	coef.m[1][3] =	(m[0][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) -
  18.768 +					(m[0][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) +
  18.769 +					(m[0][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
  18.770 +
  18.771 +	coef.m[2][0] =	(m[0][1] * (m[1][2] * m[3][3] - m[3][2] * m[1][3])) -
  18.772 +					(m[0][2] * (m[1][1] * m[3][3] - m[3][1] * m[1][3])) +
  18.773 +					(m[0][3] * (m[1][1] * m[3][2] - m[3][1] * m[1][2]));
  18.774 +	coef.m[2][1] =	(m[0][0] * (m[1][2] * m[3][3] - m[3][2] * m[1][3])) -
  18.775 +					(m[0][2] * (m[1][0] * m[3][3] - m[3][0] * m[1][3])) +
  18.776 +					(m[0][3] * (m[1][0] * m[3][2] - m[3][0] * m[1][2]));
  18.777 +	coef.m[2][2] =	(m[0][0] * (m[1][1] * m[3][3] - m[3][1] * m[1][3])) -
  18.778 +					(m[0][1] * (m[1][0] * m[3][3] - m[3][0] * m[1][3])) +
  18.779 +					(m[0][3] * (m[1][0] * m[3][1] - m[3][0] * m[1][1]));
  18.780 +	coef.m[2][3] =	(m[0][0] * (m[1][1] * m[3][2] - m[3][1] * m[1][2])) -
  18.781 +					(m[0][1] * (m[1][0] * m[3][2] - m[3][0] * m[1][2])) +
  18.782 +					(m[0][2] * (m[1][0] * m[3][1] - m[3][0] * m[1][1]));
  18.783 +
  18.784 +	coef.m[3][0] =	(m[0][1] * (m[1][2] * m[2][3] - m[2][2] * m[1][3])) -
  18.785 +					(m[0][2] * (m[1][1] * m[2][3] - m[2][1] * m[1][3])) +
  18.786 +					(m[0][3] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]));
  18.787 +	coef.m[3][1] =	(m[0][0] * (m[1][2] * m[2][3] - m[2][2] * m[1][3])) -
  18.788 +					(m[0][2] * (m[1][0] * m[2][3] - m[2][0] * m[1][3])) +
  18.789 +					(m[0][3] * (m[1][0] * m[2][2] - m[2][0] * m[1][2]));
  18.790 +	coef.m[3][2] =	(m[0][0] * (m[1][1] * m[2][3] - m[2][1] * m[1][3])) -
  18.791 +					(m[0][1] * (m[1][0] * m[2][3] - m[2][0] * m[1][3])) +
  18.792 +					(m[0][3] * (m[1][0] * m[2][1] - m[2][0] * m[1][1]));
  18.793 +	coef.m[3][3] =	(m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2])) -
  18.794 +					(m[0][1] * (m[1][0] * m[2][2] - m[2][0] * m[1][2])) +
  18.795 +					(m[0][2] * (m[1][0] * m[2][1] - m[2][0] * m[1][1]));
  18.796 +
  18.797 +	coef.transpose();
  18.798 +
  18.799 +	for(int i=0; i<4; i++) {
  18.800 +		for(int j=0; j<4; j++) {
  18.801 +			coef.m[i][j] = j%2 ? -coef.m[i][j] : coef.m[i][j];
  18.802 +			if(i%2) coef.m[i][j] = -coef.m[i][j];
  18.803 +		}
  18.804 +	}
  18.805 +
  18.806 +	return coef;
  18.807 +}
  18.808 +
  18.809 +Matrix4x4 Matrix4x4::inverse() const
  18.810 +{
  18.811 +	Matrix4x4 adj = adjoint();
  18.812 +
  18.813 +	return adj * (1.0f / determinant());
  18.814 +}
  18.815 +
  18.816 +ostream &operator <<(ostream &out, const Matrix4x4 &mat)
  18.817 +{
  18.818 +	for(int i=0; i<4; i++) {
  18.819 +		char str[100];
  18.820 +		sprintf(str, "[ %12.5f %12.5f %12.5f %12.5f ]\n", (float)mat.m[i][0], (float)mat.m[i][1], (float)mat.m[i][2], (float)mat.m[i][3]);
  18.821 +		out << str;
  18.822 +	}
  18.823 +	return out;
  18.824 +}
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/libs/vmath/matrix.h	Sun Sep 29 08:20:19 2013 +0300
    19.3 @@ -0,0 +1,260 @@
    19.4 +/*
    19.5 +libvmath - a vector math library
    19.6 +Copyright (C) 2004-2011 John Tsiombikas <nuclear@member.fsf.org>
    19.7 +
    19.8 +This program is free software: you can redistribute it and/or modify
    19.9 +it under the terms of the GNU Lesser General Public License as published
   19.10 +by the Free Software Foundation, either version 3 of the License, or
   19.11 +(at your option) any later version.
   19.12 +
   19.13 +This program is distributed in the hope that it will be useful,
   19.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   19.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   19.16 +GNU Lesser General Public License for more details.
   19.17 +
   19.18 +You should have received a copy of the GNU Lesser General Public License
   19.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
   19.20 +*/
   19.21 +
   19.22 +#ifndef VMATH_MATRIX_H_
   19.23 +#define VMATH_MATRIX_H_
   19.24 +
   19.25 +#include <stdio.h>
   19.26 +#include "vmath_types.h"
   19.27 +
   19.28 +#ifdef __cplusplus
   19.29 +extern "C" {
   19.30 +#endif	/* __cplusplus */
   19.31 +
   19.32 +/* C matrix 3x3 functions */
   19.33 +static inline void m3_identity(mat3_t m);
   19.34 +static inline void m3_cons(mat3_t m,
   19.35 +		scalar_t m11, scalar_t m12, scalar_t m13,
   19.36 +		scalar_t m21, scalar_t m22, scalar_t m23,
   19.37 +		scalar_t m31, scalar_t m32, scalar_t m33);
   19.38 +static inline void m3_copy(mat3_t dest, mat3_t src);
   19.39 +void m3_to_m4(mat4_t dest, mat3_t src);
   19.40 +
   19.41 +void m3_print(FILE *fp, mat3_t m);
   19.42 +
   19.43 +/* C matrix 4x4 functions */
   19.44 +static inline void m4_identity(mat4_t m);
   19.45 +static inline void m4_cons(mat4_t m,
   19.46 +		scalar_t m11, scalar_t m12, scalar_t m13, scalar_t m14,
   19.47 +		scalar_t m21, scalar_t m22, scalar_t m23, scalar_t m24,
   19.48 +		scalar_t m31, scalar_t m32, scalar_t m33, scalar_t m34,
   19.49 +		scalar_t m41, scalar_t m42, scalar_t m43, scalar_t m44);
   19.50 +static inline void m4_copy(mat4_t dest, mat4_t src);
   19.51 +void m4_to_m3(mat3_t dest, mat4_t src);
   19.52 +
   19.53 +static inline void m4_mult(mat4_t res, mat4_t m1, mat4_t m2);
   19.54 +
   19.55 +void m4_set_translation(mat4_t m, scalar_t x, scalar_t y, scalar_t z);
   19.56 +void m4_translate(mat4_t m, scalar_t x, scalar_t y, scalar_t z);
   19.57 +
   19.58 +void m4_rotate(mat4_t m, scalar_t x, scalar_t y, scalar_t z);
   19.59 +
   19.60 +void m4_set_rotation_x(mat4_t m, scalar_t angle);
   19.61 +void m4_rotate_x(mat4_t m, scalar_t angle);
   19.62 +void m4_set_rotation_y(mat4_t m, scalar_t angle);
   19.63 +void m4_rotate_y(mat4_t m, scalar_t angle);
   19.64 +void m4_set_rotation_z(mat4_t m, scalar_t angle);
   19.65 +void m4_rotate_z(mat4_t m, scalar_t angle);
   19.66 +/* axis-angle rotation */
   19.67 +void m4_set_rotation_axis(mat4_t m, scalar_t angle, scalar_t x, scalar_t y, scalar_t z);
   19.68 +void m4_rotate_axis(mat4_t m, scalar_t angle, scalar_t x, scalar_t y, scalar_t z);
   19.69 +/* concatentate a rotation quaternion */
   19.70 +void m4_rotate_quat(mat4_t m, quat_t q);
   19.71 +
   19.72 +void m4_set_scaling(mat4_t m, scalar_t x, scalar_t y, scalar_t z);
   19.73 +void m4_scale(mat4_t m, scalar_t x, scalar_t y, scalar_t z);
   19.74 +
   19.75 +static inline void m4_set_column(mat4_t m, vec4_t v, int idx);
   19.76 +static inline void m4_set_row(mat4_t m, vec4_t v, int idx);
   19.77 +
   19.78 +void m4_transpose(mat4_t res, mat4_t m);
   19.79 +scalar_t m4_determinant(mat4_t m);
   19.80 +void m4_adjoint(mat4_t res, mat4_t m);
   19.81 +void m4_inverse(mat4_t res, mat4_t m);
   19.82 +
   19.83 +void m4_print(FILE *fp, mat4_t m);
   19.84 +
   19.85 +#ifdef __cplusplus
   19.86 +}
   19.87 +
   19.88 +/* when included from C++ source files, also define the matrix classes */
   19.89 +#include <iostream>
   19.90 +
   19.91 +/** 3x3 matrix */
   19.92 +class Matrix3x3 {
   19.93 +public:
   19.94 +	scalar_t m[3][3];
   19.95 +
   19.96 +	static Matrix3x3 identity;
   19.97 +
   19.98 +	Matrix3x3();
   19.99 +	Matrix3x3(	scalar_t m11, scalar_t m12, scalar_t m13,
  19.100 +				scalar_t m21, scalar_t m22, scalar_t m23,
  19.101 +				scalar_t m31, scalar_t m32, scalar_t m33);
  19.102 +	Matrix3x3(const Vector3 &ivec, const Vector3 &jvec, const Vector3 &kvec);
  19.103 +	Matrix3x3(const mat3_t cmat);
  19.104 +
  19.105 +	Matrix3x3(const Matrix4x4 &mat4x4);
  19.106 +
  19.107 +	/* binary operations matrix (op) matrix */
  19.108 +	friend Matrix3x3 operator +(const Matrix3x3 &m1, const Matrix3x3 &m2);
  19.109 +	friend Matrix3x3 operator -(const Matrix3x3 &m1, const Matrix3x3 &m2);
  19.110 +	friend Matrix3x3 operator *(const Matrix3x3 &m1, const Matrix3x3 &m2);
  19.111 +
  19.112 +	friend void operator +=(Matrix3x3 &m1, const Matrix3x3 &m2);
  19.113 +	friend void operator -=(Matrix3x3 &m1, const Matrix3x3 &m2);
  19.114 +	friend void operator *=(Matrix3x3 &m1, const Matrix3x3 &m2);
  19.115 +
  19.116 +	/* binary operations matrix (op) scalar and scalar (op) matrix */
  19.117 +	friend Matrix3x3 operator *(const Matrix3x3 &mat, scalar_t scalar);
  19.118 +	friend Matrix3x3 operator *(scalar_t scalar, const Matrix3x3 &mat);
  19.119 +
  19.120 +	friend void operator *=(Matrix3x3 &mat, scalar_t scalar);
  19.121 +
  19.122 +	inline scalar_t *operator [](int index);
  19.123 +	inline const scalar_t *operator [](int index) const;
  19.124 +
  19.125 +	inline void reset_identity();
  19.126 +
  19.127 +	void translate(const Vector2 &trans);
  19.128 +	void set_translation(const Vector2 &trans);
  19.129 +
  19.130 +	void rotate(scalar_t angle);						/* 2d rotation */
  19.131 +	void rotate(const Vector3 &euler_angles);			/* 3d rotation with euler angles */
  19.132 +	void rotate(const Vector3 &axis, scalar_t angle);	/* 3d axis/angle rotation */
  19.133 +	void set_rotation(scalar_t angle);
  19.134 +	void set_rotation(const Vector3 &euler_angles);
  19.135 +	void set_rotation(const Vector3 &axis, scalar_t angle);
  19.136 +	Quaternion get_rotation_quat() const;
  19.137 +
  19.138 +	void scale(const Vector3 &scale_vec);
  19.139 +	void set_scaling(const Vector3 &scale_vec);
  19.140 +
  19.141 +	void set_column_vector(const Vector3 &vec, unsigned int col_index);
  19.142 +	void set_row_vector(const Vector3 &vec, unsigned int row_index);
  19.143 +	Vector3 get_column_vector(unsigned int col_index) const;
  19.144 +	Vector3 get_row_vector(unsigned int row_index) const;
  19.145 +
  19.146 +	void transpose();
  19.147 +	Matrix3x3 transposed() const;
  19.148 +	scalar_t determinant() const;
  19.149 +	Matrix3x3 inverse() const;
  19.150 +
  19.151 +	friend std::ostream &operator <<(std::ostream &out, const Matrix3x3 &mat);
  19.152 +};
  19.153 +
  19.154 +/* binary operations matrix (op) matrix */
  19.155 +Matrix3x3 operator +(const Matrix3x3 &m1, const Matrix3x3 &m2);
  19.156 +Matrix3x3 operator -(const Matrix3x3 &m1, const Matrix3x3 &m2);
  19.157 +Matrix3x3 operator *(const Matrix3x3 &m1, const Matrix3x3 &m2);
  19.158 +
  19.159 +void operator +=(Matrix3x3 &m1, const Matrix3x3 &m2);
  19.160 +void operator -=(Matrix3x3 &m1, const Matrix3x3 &m2);
  19.161 +void operator *=(Matrix3x3 &m1, const Matrix3x3 &m2);
  19.162 +
  19.163 +/* binary operations matrix (op) scalar and scalar (op) matrix */
  19.164 +Matrix3x3 operator *(const Matrix3x3 &mat, scalar_t scalar);
  19.165 +Matrix3x3 operator *(scalar_t scalar, const Matrix3x3 &mat);
  19.166 +
  19.167 +void operator *=(Matrix3x3 &mat, scalar_t scalar);
  19.168 +
  19.169 +std::ostream &operator <<(std::ostream &out, const Matrix3x3 &mat);
  19.170 +
  19.171 +
  19.172 +
  19.173 +/** 4x4 matrix */
  19.174 +class Matrix4x4 {
  19.175 +public:
  19.176 +	scalar_t m[4][4];
  19.177 +
  19.178 +	static Matrix4x4 identity;
  19.179 +
  19.180 +	Matrix4x4();
  19.181 +	Matrix4x4(	scalar_t m11, scalar_t m12, scalar_t m13, scalar_t m14,
  19.182 +				scalar_t m21, scalar_t m22, scalar_t m23, scalar_t m24,
  19.183 +				scalar_t m31, scalar_t m32, scalar_t m33, scalar_t m34,
  19.184 +				scalar_t m41, scalar_t m42, scalar_t m43, scalar_t m44);
  19.185 +	Matrix4x4(const mat4_t cmat);
  19.186 +
  19.187 +	Matrix4x4(const Matrix3x3 &mat3x3);
  19.188 +
  19.189 +	/* binary operations matrix (op) matrix */
  19.190 +	friend Matrix4x4 operator +(const Matrix4x4 &m1, const Matrix4x4 &m2);
  19.191 +	friend Matrix4x4 operator -(const Matrix4x4 &m1, const Matrix4x4 &m2);
  19.192 +	friend Matrix4x4 operator *(const Matrix4x4 &m1, const Matrix4x4 &m2);
  19.193 +
  19.194 +	friend void operator +=(Matrix4x4 &m1, const Matrix4x4 &m2);
  19.195 +	friend void operator -=(Matrix4x4 &m1, const Matrix4x4 &m2);
  19.196 +	friend inline void operator *=(Matrix4x4 &m1, const Matrix4x4 &m2);
  19.197 +
  19.198 +	/* binary operations matrix (op) scalar and scalar (op) matrix */
  19.199 +	friend Matrix4x4 operator *(const Matrix4x4 &mat, scalar_t scalar);
  19.200 +	friend Matrix4x4 operator *(scalar_t scalar, const Matrix4x4 &mat);
  19.201 +
  19.202 +	friend void operator *=(Matrix4x4 &mat, scalar_t scalar);
  19.203 +
  19.204 +	inline scalar_t *operator [](int index);
  19.205 +	inline const scalar_t *operator [](int index) const;
  19.206 +
  19.207 +	inline void reset_identity();
  19.208 +
  19.209 +	void translate(const Vector3 &trans);
  19.210 +	void set_translation(const Vector3 &trans);
  19.211 +	Vector3 get_translation() const;	/* extract translation */
  19.212 +
  19.213 +	void rotate(const Vector3 &euler_angles);			/* 3d rotation with euler angles */
  19.214 +	void rotate(const Vector3 &axis, scalar_t angle);	/* 3d axis/angle rotation */
  19.215 +	void rotate(const Quaternion &quat);
  19.216 +	void set_rotation(const Vector3 &euler_angles);
  19.217 +	void set_rotation(const Vector3 &axis, scalar_t angle);
  19.218 +	void set_rotation(const Quaternion &quat);
  19.219 +	Quaternion get_rotation_quat() const;		/* extract rotation */
  19.220 +
  19.221 +	void scale(const Vector4 &scale_vec);
  19.222 +	void set_scaling(const Vector4 &scale_vec);
  19.223 +	Vector3 get_scaling() const;		/* extract scaling */
  19.224 +
  19.225 +	void set_perspective(float vfov, float aspect, float znear, float zfar);
  19.226 +	void set_orthographic(float left, float right, float bottom, float top, float znear = -1.0, float zfar = 1.0);
  19.227 +
  19.228 +	void set_column_vector(const Vector4 &vec, unsigned int col_index);
  19.229 +	void set_row_vector(const Vector4 &vec, unsigned int row_index);
  19.230 +	Vector4 get_column_vector(unsigned int col_index) const;
  19.231 +	Vector4 get_row_vector(unsigned int row_index) const;
  19.232 +
  19.233 +	void transpose();
  19.234 +	Matrix4x4 transposed() const;
  19.235 +	scalar_t determinant() const;
  19.236 +	Matrix4x4 adjoint() const;
  19.237 +	Matrix4x4 inverse() const;
  19.238 +
  19.239 +	friend std::ostream &operator <<(std::ostream &out, const Matrix4x4 &mat);
  19.240 +};
  19.241 +
  19.242 +/* binary operations matrix (op) matrix */
  19.243 +Matrix4x4 operator +(const Matrix4x4 &m1, const Matrix4x4 &m2);
  19.244 +Matrix4x4 operator -(const Matrix4x4 &m1, const Matrix4x4 &m2);
  19.245 +inline Matrix4x4 operator *(const Matrix4x4 &m1, const Matrix4x4 &m2);
  19.246 +
  19.247 +void operator +=(Matrix4x4 &m1, const Matrix4x4 &m2);
  19.248 +void operator -=(Matrix4x4 &m1, const Matrix4x4 &m2);
  19.249 +inline void operator *=(Matrix4x4 &m1, const Matrix4x4 &m2);
  19.250 +
  19.251 +/* binary operations matrix (op) scalar and scalar (op) matrix */
  19.252 +Matrix4x4 operator *(const Matrix4x4 &mat, scalar_t scalar);
  19.253 +Matrix4x4 operator *(scalar_t scalar, const Matrix4x4 &mat);
  19.254 +
  19.255 +void operator *=(Matrix4x4 &mat, scalar_t scalar);
  19.256 +
  19.257 +std::ostream &operator <<(std::ostream &out, const Matrix4x4 &mat);
  19.258 +
  19.259 +#endif	/* __cplusplus */
  19.260 +
  19.261 +#include "matrix.inl"
  19.262 +
  19.263 +#endif	/* VMATH_MATRIX_H_ */
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/libs/vmath/matrix.inl	Sun Sep 29 08:20:19 2013 +0300
    20.3 @@ -0,0 +1,200 @@
    20.4 +/*
    20.5 +libvmath - a vector math library
    20.6 +Copyright (C) 2004-2011 John Tsiombikas <nuclear@member.fsf.org>
    20.7 +
    20.8 +This program is free software: you can redistribute it and/or modify
    20.9 +it under the terms of the GNU Lesser General Public License as published
   20.10 +by the Free Software Foundation, either version 3 of the License, or
   20.11 +(at your option) any later version.
   20.12 +
   20.13 +This program is distributed in the hope that it will be useful,
   20.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   20.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   20.16 +GNU Lesser General Public License for more details.
   20.17 +
   20.18 +You should have received a copy of the GNU Lesser General Public License
   20.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
   20.20 +*/
   20.21 +
   20.22 +#include <string.h>
   20.23 +
   20.24 +#ifdef __cplusplus
   20.25 +extern "C" {
   20.26 +#endif	/* __cplusplus */
   20.27 +
   20.28 +/* C matrix 3x3 functions */
   20.29 +static inline void m3_identity(mat3_t m)
   20.30 +{
   20.31 +	static const mat3_t id = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
   20.32 +	memcpy(m, id, sizeof id);
   20.33 +}
   20.34 +
   20.35 +static inline void m3_cons(mat3_t m,
   20.36 +		scalar_t m11, scalar_t m12, scalar_t m13,
   20.37 +		scalar_t m21, scalar_t m22, scalar_t m23,
   20.38 +		scalar_t m31, scalar_t m32, scalar_t m33)
   20.39 +{
   20.40 +	m[0][0] = m11; m[0][1] = m12; m[0][2] = m13;
   20.41 +	m[1][0] = m21; m[1][1] = m22; m[1][2] = m23;
   20.42 +	m[2][0] = m31; m[2][1] = m32; m[2][2] = m33;
   20.43 +}
   20.44 +
   20.45 +static inline void m3_copy(mat3_t dest, mat3_t src)
   20.46 +{
   20.47 +	memcpy(dest, src, sizeof(mat3_t));
   20.48 +}
   20.49 +
   20.50 +
   20.51 +/* C matrix 4x4 functions */
   20.52 +static inline void m4_identity(mat4_t m)
   20.53 +{
   20.54 +	static const mat4_t id = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
   20.55 +	memcpy(m, id, sizeof id);
   20.56 +}
   20.57 +
   20.58 +static inline void m4_cons(mat4_t m,
   20.59 +		scalar_t m11, scalar_t m12, scalar_t m13, scalar_t m14,
   20.60 +		scalar_t m21, scalar_t m22, scalar_t m23, scalar_t m24,
   20.61 +		scalar_t m31, scalar_t m32, scalar_t m33, scalar_t m34,
   20.62 +		scalar_t m41, scalar_t m42, scalar_t m43, scalar_t m44)
   20.63 +{
   20.64 +	m[0][0] = m11; m[0][1] = m12; m[0][2] = m13; m[0][3] = m14;
   20.65 +	m[1][0] = m21; m[1][1] = m22; m[1][2] = m23; m[1][3] = m24;
   20.66 +	m[2][0] = m31; m[2][1] = m32; m[2][2] = m33; m[2][3] = m34;
   20.67 +	m[3][0] = m41; m[3][1] = m42; m[3][2] = m43; m[3][3] = m44;
   20.68 +}
   20.69 +
   20.70 +static inline void m4_copy(mat4_t dest, mat4_t src)
   20.71 +{
   20.72 +	memcpy(dest, src, sizeof(mat4_t));
   20.73 +}
   20.74 +
   20.75 +static inline void m4_mult(mat4_t res, mat4_t m1, mat4_t m2)
   20.76 +{
   20.77 +	mat4_t tmp;
   20.78 +
   20.79 +	/*
   20.80 +	int i, j;
   20.81 +	for(i=0; i<4; i++) {
   20.82 +		for(j=0; j<4; j++) {
   20.83 +			tmp[i][j] = m1[i][0] * m2[0][j] + m1[i][1] * m2[1][j] + m1[i][2] * m2[2][j] + m1[i][3] * m2[3][j];
   20.84 +		}
   20.85 +	}
   20.86 +	*/
   20.87 +
   20.88 +	tmp[0][0] = m1[0][0] * m2[0][0] + m1[0][1] * m2[1][0] + m1[0][2] * m2[2][0] + m1[0][3] * m2[3][0];
   20.89 +	tmp[0][1] = m1[0][0] * m2[0][1] + m1[0][1] * m2[1][1] + m1[0][2] * m2[2][1] + m1[0][3] * m2[3][1];
   20.90 +	tmp[0][2] = m1[0][0] * m2[0][2] + m1[0][1] * m2[1][2] + m1[0][2] * m2[2][2] + m1[0][3] * m2[3][2];
   20.91 +	tmp[0][3] = m1[0][0] * m2[0][3] + m1[0][1] * m2[1][3] + m1[0][2] * m2[2][3] + m1[0][3] * m2[3][3];
   20.92 +
   20.93 +	tmp[1][0] = m1[1][0] * m2[0][0] + m1[1][1] * m2[1][0] + m1[1][2] * m2[2][0] + m1[1][3] * m2[3][0];
   20.94 +	tmp[1][1] = m1[1][0] * m2[0][1] + m1[1][1] * m2[1][1] + m1[1][2] * m2[2][1] + m1[1][3] * m2[3][1];
   20.95 +	tmp[1][2] = m1[1][0] * m2[0][2] + m1[1][1] * m2[1][2] + m1[1][2] * m2[2][2] + m1[1][3] * m2[3][2];
   20.96 +	tmp[1][3] = m1[1][0] * m2[0][3] + m1[1][1] * m2[1][3] + m1[1][2] * m2[2][3] + m1[1][3] * m2[3][3];
   20.97 +
   20.98 +	tmp[2][0] = m1[2][0] * m2[0][0] + m1[2][1] * m2[1][0] + m1[2][2] * m2[2][0] + m1[2][3] * m2[3][0];
   20.99 +	tmp[2][1] = m1[2][0] * m2[0][1] + m1[2][1] * m2[1][1] + m1[2][2] * m2[2][1] + m1[2][3] * m2[3][1];
  20.100 +	tmp[2][2] = m1[2][0] * m2[0][2] + m1[2][1] * m2[1][2] + m1[2][2] * m2[2][2] + m1[2][3] * m2[3][2];
  20.101 +	tmp[2][3] = m1[2][0] * m2[0][3] + m1[2][1] * m2[1][3] + m1[2][2] * m2[2][3] + m1[2][3] * m2[3][3];
  20.102 +
  20.103 +	tmp[3][0] = m1[3][0] * m2[0][0] + m1[3][1] * m2[1][0] + m1[3][2] * m2[2][0] + m1[3][3] * m2[3][0];
  20.104 +	tmp[3][1] = m1[3][0] * m2[0][1] + m1[3][1] * m2[1][1] + m1[3][2] * m2[2][1] + m1[3][3] * m2[3][1];
  20.105 +	tmp[3][2] = m1[3][0] * m2[0][2] + m1[3][1] * m2[1][2] + m1[3][2] * m2[2][2] + m1[3][3] * m2[3][2];
  20.106 +	tmp[3][3] = m1[3][0] * m2[0][3] + m1[3][1] * m2[1][3] + m1[3][2] * m2[2][3] + m1[3][3] * m2[3][3];
  20.107 +
  20.108 +	m4_copy(res, tmp);
  20.109 +}
  20.110 +
  20.111 +static inline void m4_set_column(mat4_t m, vec4_t v, int idx)
  20.112 +{
  20.113 +	m[0][idx] = v.x;
  20.114 +	m[1][idx] = v.y;
  20.115 +	m[2][idx] = v.z;
  20.116 +	m[3][idx] = v.w;
  20.117 +}
  20.118 +
  20.119 +static inline void m4_set_row(mat4_t m, vec4_t v, int idx)
  20.120 +{
  20.121 +	m[idx][0] = v.x;
  20.122 +	m[idx][1] = v.y;
  20.123 +	m[idx][2] = v.z;
  20.124 +	m[idx][3] = v.w;
  20.125 +}
  20.126 +
  20.127 +#ifdef __cplusplus
  20.128 +}	/* extern "C" */
  20.129 +
  20.130 +
  20.131 +/* unrolled to hell and inline */
  20.132 +inline Matrix4x4 operator *(const Matrix4x4 &m1, const Matrix4x4 &m2)
  20.133 +{
  20.134 +	Matrix4x4 res;
  20.135 +
  20.136 +	/*
  20.137 +	for(i=0; i<4; i++) {
  20.138 +		for(j=0; j<4; j++) {
  20.139 +			res.m[i][j] = m1.m[i][0] * m2.m[0][j] + m1.m[i][1] * m2.m[1][j] + m1.m[i][2] * m2.m[2][j] + m1.m[i][3] * m2.m[3][j];
  20.140 +		}
  20.141 +	}
  20.142 +	*/
  20.143 +
  20.144 +	res.m[0][0] = m1.m[0][0] * m2.m[0][0] + m1.m[0][1] * m2.m[1][0] + m1.m[0][2] * m2.m[2][0] + m1.m[0][3] * m2.m[3][0];
  20.145 +	res.m[0][1] = m1.m[0][0] * m2.m[0][1] + m1.m[0][1] * m2.m[1][1] + m1.m[0][2] * m2.m[2][1] + m1.m[0][3] * m2.m[3][1];
  20.146 +	res.m[0][2] = m1.m[0][0] * m2.m[0][2] + m1.m[0][1] * m2.m[1][2] + m1.m[0][2] * m2.m[2][2] + m1.m[0][3] * m2.m[3][2];
  20.147 +	res.m[0][3] = m1.m[0][0] * m2.m[0][3] + m1.m[0][1] * m2.m[1][3] + m1.m[0][2] * m2.m[2][3] + m1.m[0][3] * m2.m[3][3];
  20.148 +
  20.149 +	res.m[1][0] = m1.m[1][0] * m2.m[0][0] + m1.m[1][1] * m2.m[1][0] + m1.m[1][2] * m2.m[2][0] + m1.m[1][3] * m2.m[3][0];
  20.150 +	res.m[1][1] = m1.m[1][0] * m2.m[0][1] + m1.m[1][1] * m2.m[1][1] + m1.m[1][2] * m2.m[2][1] + m1.m[1][3] * m2.m[3][1];
  20.151 +	res.m[1][2] = m1.m[1][0] * m2.m[0][2] + m1.m[1][1] * m2.m[1][2] + m1.m[1][2] * m2.m[2][2] + m1.m[1][3] * m2.m[3][2];
  20.152 +	res.m[1][3] = m1.m[1][0] * m2.m[0][3] + m1.m[1][1] * m2.m[1][3] + m1.m[1][2] * m2.m[2][3] + m1.m[1][3] * m2.m[3][3];
  20.153 +
  20.154 +	res.m[2][0] = m1.m[2][0] * m2.m[0][0] + m1.m[2][1] * m2.m[1][0] + m1.m[2][2] * m2.m[2][0] + m1.m[2][3] * m2.m[3][0];
  20.155 +	res.m[2][1] = m1.m[2][0] * m2.m[0][1] + m1.m[2][1] * m2.m[1][1] + m1.m[2][2] * m2.m[2][1] + m1.m[2][3] * m2.m[3][1];
  20.156 +	res.m[2][2] = m1.m[2][0] * m2.m[0][2] + m1.m[2][1] * m2.m[1][2] + m1.m[2][2] * m2.m[2][2] + m1.m[2][3] * m2.m[3][2];
  20.157 +	res.m[2][3] = m1.m[2][0] * m2.m[0][3] + m1.m[2][1] * m2.m[1][3] + m1.m[2][2] * m2.m[2][3] + m1.m[2][3] * m2.m[3][3];
  20.158 +
  20.159 +	res.m[3][0] = m1.m[3][0] * m2.m[0][0] + m1.m[3][1] * m2.m[1][0] + m1.m[3][2] * m2.m[2][0] + m1.m[3][3] * m2.m[3][0];
  20.160 +	res.m[3][1] = m1.m[3][0] * m2.m[0][1] + m1.m[3][1] * m2.m[1][1] + m1.m[3][2] * m2.m[2][1] + m1.m[3][3] * m2.m[3][1];
  20.161 +	res.m[3][2] = m1.m[3][0] * m2.m[0][2] + m1.m[3][1] * m2.m[1][2] + m1.m[3][2] * m2.m[2][2] + m1.m[3][3] * m2.m[3][2];
  20.162 +	res.m[3][3] = m1.m[3][0] * m2.m[0][3] + m1.m[3][1] * m2.m[1][3] + m1.m[3][2] * m2.m[2][3] + m1.m[3][3] * m2.m[3][3];
  20.163 +
  20.164 +	return res;
  20.165 +}
  20.166 +
  20.167 +inline void operator *=(Matrix4x4 &m1, const Matrix4x4 &m2)
  20.168 +{
  20.169 +	Matrix4x4 res = m1 * m2;
  20.170 +	m1 = res;
  20.171 +}
  20.172 +
  20.173 +
  20.174 +inline scalar_t *Matrix3x3::operator [](int index)
  20.175 +{
  20.176 +	return m[index];
  20.177 +}
  20.178 +
  20.179 +inline const scalar_t *Matrix3x3::operator [](int index) const
  20.180 +{
  20.181 +	return m[index];
  20.182 +}
  20.183 +
  20.184 +inline void Matrix3x3::reset_identity()
  20.185 +{
  20.186 +	*this = identity;
  20.187 +}
  20.188 +
  20.189 +inline scalar_t *Matrix4x4::operator [](int index)
  20.190 +{
  20.191 +	return m[index];
  20.192 +}
  20.193 +
  20.194 +inline const scalar_t *Matrix4x4::operator [](int index) const
  20.195 +{
  20.196 +	return m[index];
  20.197 +}
  20.198 +
  20.199 +inline void Matrix4x4::reset_identity()
  20.200 +{
  20.201 +	*this = identity;
  20.202 +}
  20.203 +#endif	/* __cplusplus */
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/libs/vmath/matrix_c.c	Sun Sep 29 08:20:19 2013 +0300
    21.3 @@ -0,0 +1,292 @@
    21.4 +/*
    21.5 +libvmath - a vector math library
    21.6 +Copyright (C) 2004-2011 John Tsiombikas <nuclear@member.fsf.org>
    21.7 +
    21.8 +This program is free software: you can redistribute it and/or modify
    21.9 +it under the terms of the GNU Lesser General Public License as published
   21.10 +by the Free Software Foundation, either version 3 of the License, or
   21.11 +(at your option) any later version.
   21.12 +
   21.13 +This program is distributed in the hope that it will be useful,
   21.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   21.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   21.16 +GNU Lesser General Public License for more details.
   21.17 +
   21.18 +You should have received a copy of the GNU Lesser General Public License
   21.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
   21.20 +*/
   21.21 +
   21.22 +
   21.23 +#include <stdio.h>
   21.24 +#include "matrix.h"
   21.25 +#include "vector.h"
   21.26 +#include "quat.h"
   21.27 +
   21.28 +void m3_to_m4(mat4_t dest, mat3_t src)
   21.29 +{
   21.30 +	int i, j;
   21.31 +
   21.32 +	memset(dest, 0, sizeof(mat4_t));
   21.33 +	for(i=0; i<3; i++) {
   21.34 +		for(j=0; j<3; j++) {
   21.35 +			dest[i][j] = src[i][j];
   21.36 +		}
   21.37 +	}
   21.38 +	dest[3][3] = 1.0;
   21.39 +}
   21.40 +
   21.41 +void m3_print(FILE *fp, mat3_t m)
   21.42 +{
   21.43 +	int i;
   21.44 +	for(i=0; i<3; i++) {
   21.45 +		fprintf(fp, "[ %12.5f %12.5f %12.5f ]\n", (float)m[i][0], (float)m[i][1], (float)m[i][2]);
   21.46 +	}
   21.47 +}
   21.48 +
   21.49 +/* C matrix 4x4 functions */
   21.50 +void m4_to_m3(mat3_t dest, mat4_t src)
   21.51 +{
   21.52 +	int i, j;
   21.53 +	for(i=0; i<3; i++) {
   21.54 +		for(j=0; j<3; j++) {
   21.55 +			dest[i][j] = src[i][j];
   21.56 +		}
   21.57 +	}
   21.58 +}
   21.59 +
   21.60 +void m4_set_translation(mat4_t m, scalar_t x, scalar_t y, scalar_t z)
   21.61 +{
   21.62 +	m4_identity(m);
   21.63 +	m[0][3] = x;
   21.64 +	m[1][3] = y;
   21.65 +	m[2][3] = z;
   21.66 +}
   21.67 +
   21.68 +void m4_translate(mat4_t m, scalar_t x, scalar_t y, scalar_t z)
   21.69 +{
   21.70 +	mat4_t tm;
   21.71 +	m4_set_translation(tm, x, y, z);
   21.72 +	m4_mult(m, m, tm);
   21.73 +}
   21.74 +
   21.75 +void m4_rotate(mat4_t m, scalar_t x, scalar_t y, scalar_t z)
   21.76 +{
   21.77 +	m4_rotate_x(m, x);
   21.78 +	m4_rotate_y(m, y);
   21.79 +	m4_rotate_z(m, z);
   21.80 +}
   21.81 +
   21.82 +void m4_set_rotation_x(mat4_t m, scalar_t angle)
   21.83 +{
   21.84 +	m4_identity(m);
   21.85 +	m[1][1] = cos(angle); m[1][2] = -sin(angle);
   21.86 +	m[2][1] = sin(angle); m[2][2] = cos(angle);
   21.87 +}
   21.88 +
   21.89 +void m4_rotate_x(mat4_t m, scalar_t angle)
   21.90 +{
   21.91 +	mat4_t rm;
   21.92 +	m4_set_rotation_x(m, angle);
   21.93 +	m4_mult(m, m, rm);
   21.94 +}
   21.95 +
   21.96 +void m4_set_rotation_y(mat4_t m, scalar_t angle)
   21.97 +{
   21.98 +	m4_identity(m);
   21.99 +	m[0][0] = cos(angle); m[0][2] = sin(angle);
  21.100 +	m[2][0] = -sin(angle); m[2][2] = cos(angle);
  21.101 +}
  21.102 +
  21.103 +void m4_rotate_y(mat4_t m, scalar_t angle)
  21.104 +{
  21.105 +	mat4_t rm;
  21.106 +	m4_set_rotation_y(rm, angle);
  21.107 +	m4_mult(m, m, rm);
  21.108 +}
  21.109 +
  21.110 +void m4_set_rotation_z(mat4_t m, scalar_t angle)
  21.111 +{
  21.112 +	m4_identity(m);
  21.113 +	m[0][0] = cos(angle); m[0][1] = -sin(angle);
  21.114 +	m[1][0] = sin(angle); m[1][1] = cos(angle);
  21.115 +}
  21.116 +
  21.117 +void m4_rotate_z(mat4_t m, scalar_t angle)
  21.118 +{
  21.119 +	mat4_t rm;
  21.120 +	m4_set_rotation_z(rm, angle);
  21.121 +	m4_mult(m, m, rm);
  21.122 +}
  21.123 +
  21.124 +void m4_set_rotation_axis(mat4_t m, scalar_t angle, scalar_t x, scalar_t y, scalar_t z)
  21.125 +{
  21.126 +	scalar_t sina = sin(angle);
  21.127 +	scalar_t cosa = cos(angle);
  21.128 +	scalar_t one_minus_cosa = 1.0 - cosa;
  21.129 +	scalar_t nxsq = x * x;
  21.130 +	scalar_t nysq = y * y;
  21.131 +	scalar_t nzsq = z * z;
  21.132 +
  21.133 +	m[0][0] = nxsq + (1.0 - nxsq) * cosa;
  21.134 +	m[0][1] = x * y * one_minus_cosa - z * sina;
  21.135 +	m[0][2] = x * z * one_minus_cosa + y * sina;
  21.136 +	m[1][0] = x * y * one_minus_cosa + z * sina;
  21.137 +	m[1][1] = nysq + (1.0 - nysq) * cosa;
  21.138 +	m[1][2] = y * z * one_minus_cosa - x * sina;
  21.139 +	m[2][0] = x * z * one_minus_cosa - y * sina;
  21.140 +	m[2][1] = y * z * one_minus_cosa + x * sina;
  21.141 +	m[2][2] = nzsq + (1.0 - nzsq) * cosa;
  21.142 +
  21.143 +	/* the rest are identity */
  21.144 +	m[3][0] = m[3][1] = m[3][2] = m[0][3] = m[1][3] = m[2][3] = 0.0;
  21.145 +	m[3][3] = 1.0;
  21.146 +}
  21.147 +
  21.148 +void m4_rotate_axis(mat4_t m, scalar_t angle, scalar_t x, scalar_t y, scalar_t z)
  21.149 +{
  21.150 +	mat4_t xform;
  21.151 +	m4_set_rotation_axis(xform, angle, x, y, z);
  21.152 +	m4_mult(m, m, xform);
  21.153 +}
  21.154 +
  21.155 +void m4_rotate_quat(mat4_t m, quat_t q)
  21.156 +{
  21.157 +	mat4_t rm;
  21.158 +	quat_to_mat4(rm, q);
  21.159 +	m4_mult(m, m, rm);
  21.160 +}
  21.161 +
  21.162 +void m4_scale(mat4_t m, scalar_t x, scalar_t y, scalar_t z)
  21.163 +{
  21.164 +	mat4_t sm;
  21.165 +	m4_identity(sm);
  21.166 +	sm[0][0] = x;
  21.167 +	sm[1][1] = y;
  21.168 +	sm[2][2] = z;
  21.169 +	m4_mult(m, m, sm);
  21.170 +}
  21.171 +
  21.172 +void m4_transpose(mat4_t res, mat4_t m)
  21.173 +{
  21.174 +	int i, j;
  21.175 +	mat4_t tmp;
  21.176 +	m4_copy(tmp, m);
  21.177 +
  21.178 +	for(i=0; i<4; i++) {
  21.179 +		for(j=0; j<4; j++) {
  21.180 +			res[i][j] = tmp[j][i];
  21.181 +		}
  21.182 +	}
  21.183 +}
  21.184 +
  21.185 +scalar_t m4_determinant(mat4_t m)
  21.186 +{
  21.187 +	scalar_t det11 =	(m[1][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
  21.188 +						(m[1][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) +
  21.189 +						(m[1][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2]));
  21.190 +
  21.191 +	scalar_t det12 =	(m[1][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
  21.192 +						(m[1][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
  21.193 +						(m[1][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2]));
  21.194 +
  21.195 +	scalar_t det13 =	(m[1][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) -
  21.196 +						(m[1][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
  21.197 +						(m[1][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
  21.198 +
  21.199 +	scalar_t det14 =	(m[1][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) -
  21.200 +						(m[1][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) +
  21.201 +						(m[1][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
  21.202 +
  21.203 +	return m[0][0] * det11 - m[0][1] * det12 + m[0][2] * det13 - m[0][3] * det14;
  21.204 +}
  21.205 +
  21.206 +void m4_adjoint(mat4_t res, mat4_t m)
  21.207 +{
  21.208 +	int i, j;
  21.209 +	mat4_t coef;
  21.210 +
  21.211 +	coef[0][0] =	(m[1][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
  21.212 +					(m[1][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) +
  21.213 +					(m[1][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2]));
  21.214 +	coef[0][1] =	(m[1][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
  21.215 +					(m[1][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
  21.216 +					(m[1][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2]));
  21.217 +	coef[0][2] =	(m[1][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) -
  21.218 +					(m[1][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
  21.219 +					(m[1][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
  21.220 +	coef[0][3] =	(m[1][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) -
  21.221 +					(m[1][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) +
  21.222 +					(m[1][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
  21.223 +
  21.224 +	coef[1][0] =	(m[0][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
  21.225 +					(m[0][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) +
  21.226 +					(m[0][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2]));
  21.227 +	coef[1][1] =	(m[0][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
  21.228 +					(m[0][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
  21.229 +					(m[0][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2]));
  21.230 +	coef[1][2] =	(m[0][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) -
  21.231 +					(m[0][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
  21.232 +					(m[0][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
  21.233 +	coef[1][3] =	(m[0][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) -
  21.234 +					(m[0][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) +
  21.235 +					(m[0][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
  21.236 +
  21.237 +	coef[2][0] =	(m[0][1] * (m[1][2] * m[3][3] - m[3][2] * m[1][3])) -
  21.238 +					(m[0][2] * (m[1][1] * m[3][3] - m[3][1] * m[1][3])) +
  21.239 +					(m[0][3] * (m[1][1] * m[3][2] - m[3][1] * m[1][2]));
  21.240 +	coef[2][1] =	(m[0][0] * (m[1][2] * m[3][3] - m[3][2] * m[1][3])) -
  21.241 +					(m[0][2] * (m[1][0] * m[3][3] - m[3][0] * m[1][3])) +
  21.242 +					(m[0][3] * (m[1][0] * m[3][2] - m[3][0] * m[1][2]));
  21.243 +	coef[2][2] =	(m[0][0] * (m[1][1] * m[3][3] - m[3][1] * m[1][3])) -
  21.244 +					(m[0][1] * (m[1][0] * m[3][3] - m[3][0] * m[1][3])) +
  21.245 +					(m[0][3] * (m[1][0] * m[3][1] - m[3][0] * m[1][1]));
  21.246 +	coef[2][3] =	(m[0][0] * (m[1][1] * m[3][2] - m[3][1] * m[1][2])) -
  21.247 +					(m[0][1] * (m[1][0] * m[3][2] - m[3][0] * m[1][2])) +
  21.248 +					(m[0][2] * (m[1][0] * m[3][1] - m[3][0] * m[1][1]));
  21.249 +
  21.250 +	coef[3][0] =	(m[0][1] * (m[1][2] * m[2][3] - m[2][2] * m[1][3])) -
  21.251 +					(m[0][2] * (m[1][1] * m[2][3] - m[2][1] * m[1][3])) +
  21.252 +					(m[0][3] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]));
  21.253 +	coef[3][1] =	(m[0][0] * (m[1][2] * m[2][3] - m[2][2] * m[1][3])) -
  21.254 +					(m[0][2] * (m[1][0] * m[2][3] - m[2][0] * m[1][3])) +
  21.255 +					(m[0][3] * (m[1][0] * m[2][2] - m[2][0] * m[1][2]));
  21.256 +	coef[3][2] =	(m[0][0] * (m[1][1] * m[2][3] - m[2][1] * m[1][3])) -
  21.257 +					(m[0][1] * (m[1][0] * m[2][3] - m[2][0] * m[1][3])) +
  21.258 +					(m[0][3] * (m[1][0] * m[2][1] - m[2][0] * m[1][1]));
  21.259 +	coef[3][3] =	(m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2])) -
  21.260 +					(m[0][1] * (m[1][0] * m[2][2] - m[2][0] * m[1][2])) +
  21.261 +					(m[0][2] * (m[1][0] * m[2][1] - m[2][0] * m[1][1]));
  21.262 +
  21.263 +	m4_transpose(res, coef);
  21.264 +
  21.265 +	for(i=0; i<4; i++) {
  21.266 +		for(j=0; j<4; j++) {
  21.267 +			res[i][j] = j % 2 ? -res[i][j] : res[i][j];
  21.268 +			if(i % 2) res[i][j] = -res[i][j];
  21.269 +		}
  21.270 +	}
  21.271 +}
  21.272 +
  21.273 +void m4_inverse(mat4_t res, mat4_t m)
  21.274 +{
  21.275 +	int i, j;
  21.276 +	mat4_t adj;
  21.277 +	scalar_t det;
  21.278 +
  21.279 +	m4_adjoint(adj, m);
  21.280 +	det = m4_determinant(m);
  21.281 +	
  21.282 +	for(i=0; i<4; i++) {
  21.283 +		for(j=0; j<4; j++) {
  21.284 +			res[i][j] = adj[i][j] / det;
  21.285 +		}
  21.286 +	}
  21.287 +}
  21.288 +
  21.289 +void m4_print(FILE *fp, mat4_t m)
  21.290 +{
  21.291 +	int i;
  21.292 +	for(i=0; i<4; i++) {
  21.293 +		fprintf(fp, "[ %12.5f %12.5f %12.5f %12.5f ]\n", (float)m[i][0], (float)m[i][1], (float)m[i][2], (float)m[i][3]);
  21.294 +	}
  21.295 +}
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/libs/vmath/quat.cc	Sun Sep 29 08:20:19 2013 +0300
    22.3 @@ -0,0 +1,212 @@
    22.4 +#include "quat.h"
    22.5 +#include "vmath.h"
    22.6 +
    22.7 +Quaternion::Quaternion()
    22.8 +{
    22.9 +	s = 1.0;
   22.10 +	v.x = v.y = v.z = 0.0;
   22.11 +}
   22.12 +
   22.13 +Quaternion::Quaternion(scalar_t s, const Vector3 &v)
   22.14 +{
   22.15 +	this->s = s;
   22.16 +	this->v = v;
   22.17 +}
   22.18 +
   22.19 +Quaternion::Quaternion(scalar_t s, scalar_t x, scalar_t y, scalar_t z)
   22.20 +{
   22.21 +	v.x = x;
   22.22 +	v.y = y;
   22.23 +	v.z = z;
   22.24 +	this->s = s;
   22.25 +}
   22.26 +
   22.27 +Quaternion::Quaternion(const Vector3 &axis, scalar_t angle)
   22.28 +{
   22.29 +	set_rotation(axis, angle);
   22.30 +}
   22.31 +
   22.32 +Quaternion::Quaternion(const quat_t &quat)
   22.33 +{
   22.34 +	v.x = quat.x;
   22.35 +	v.y = quat.y;
   22.36 +	v.z = quat.z;
   22.37 +	s = quat.w;
   22.38 +}
   22.39 +
   22.40 +Quaternion Quaternion::operator +(const Quaternion &quat) const
   22.41 +{
   22.42 +	return Quaternion(s + quat.s, v + quat.v);
   22.43 +}
   22.44 +
   22.45 +Quaternion Quaternion::operator -(const Quaternion &quat) const
   22.46 +{
   22.47 +	return Quaternion(s - quat.s, v - quat.v);
   22.48 +}
   22.49 +
   22.50 +Quaternion Quaternion::operator -() const
   22.51 +{
   22.52 +	return Quaternion(-s, -v);
   22.53 +}
   22.54 +
   22.55 +/** Quaternion Multiplication:
   22.56 + * Q1*Q2 = [s1*s2 - v1.v2,  s1*v2 + s2*v1 + v1(x)v2]
   22.57 + */
   22.58 +Quaternion Quaternion::operator *(const Quaternion &quat) const
   22.59 +{
   22.60 +	Quaternion newq;
   22.61 +	newq.s = s * quat.s - dot_product(v, quat.v);
   22.62 +	newq.v = quat.v * s + v * quat.s + cross_product(v, quat.v);
   22.63 +	return newq;
   22.64 +}
   22.65 +
   22.66 +void Quaternion::operator +=(const Quaternion &quat)
   22.67 +{
   22.68 +	*this = Quaternion(s + quat.s, v + quat.v);
   22.69 +}
   22.70 +
   22.71 +void Quaternion::operator -=(const Quaternion &quat)
   22.72 +{
   22.73 +	*this = Quaternion(s - quat.s, v - quat.v);
   22.74 +}
   22.75 +
   22.76 +void Quaternion::operator *=(const Quaternion &quat)
   22.77 +{
   22.78 +	*this = *this * quat;
   22.79 +}
   22.80 +
   22.81 +void Quaternion::reset_identity()
   22.82 +{
   22.83 +	s = 1.0;
   22.84 +	v.x = v.y = v.z = 0.0;
   22.85 +}
   22.86 +
   22.87 +Quaternion Quaternion::conjugate() const
   22.88 +{
   22.89 +	return Quaternion(s, -v);
   22.90 +}
   22.91 +
   22.92 +scalar_t Quaternion::length() const
   22.93 +{
   22.94 +	return (scalar_t)sqrt(v.x*v.x + v.y*v.y + v.z*v.z + s*s);
   22.95 +}
   22.96 +
   22.97 +/** Q * ~Q = ||Q||^2 */
   22.98 +scalar_t Quaternion::length_sq() const
   22.99 +{
  22.100 +	return v.x*v.x + v.y*v.y + v.z*v.z + s*s;
  22.101 +}
  22.102 +
  22.103 +void Quaternion::normalize()
  22.104 +{
  22.105 +	scalar_t len = (scalar_t)sqrt(v.x*v.x + v.y*v.y + v.z*v.z + s*s);
  22.106 +	v.x /= len;
  22.107 +	v.y /= len;
  22.108 +	v.z /= len;
  22.109 +	s /= len;
  22.110 +}
  22.111 +
  22.112 +Quaternion Quaternion::normalized() const
  22.113 +{
  22.114 +	Quaternion nq = *this;
  22.115 +	scalar_t len = (scalar_t)sqrt(v.x*v.x + v.y*v.y + v.z*v.z + s*s);
  22.116 +	nq.v.x /= len;
  22.117 +	nq.v.y /= len;
  22.118 +	nq.v.z /= len;
  22.119 +	nq.s /= len;
  22.120 +	return nq;
  22.121 +}
  22.122 +
  22.123 +/** Quaternion Inversion: Q^-1 = ~Q / ||Q||^2 */
  22.124 +Quaternion Quaternion::inverse() const
  22.125 +{
  22.126 +	Quaternion inv = conjugate();
  22.127 +	scalar_t lensq = length_sq();
  22.128 +	inv.v /= lensq;
  22.129 +	inv.s /= lensq;
  22.130 +
  22.131 +	return inv;
  22.132 +}
  22.133 +
  22.134 +
  22.135 +void Quaternion::set_rotation(const Vector3 &axis, scalar_t angle)
  22.136 +{
  22.137 +	scalar_t half_angle = angle / 2.0;
  22.138 +	s = cos(half_angle);
  22.139 +	v = axis * sin(half_angle);
  22.140 +}
  22.141 +
  22.142 +void Quaternion::rotate(const Vector3 &axis, scalar_t angle)
  22.143 +{
  22.144 +	Quaternion q;
  22.145 +	scalar_t half_angle = angle / 2.0;
  22.146 +	q.s = cos(half_angle);
  22.147 +	q.v = axis * sin(half_angle);
  22.148 +
  22.149 +	*this *= q;
  22.150 +}
  22.151 +
  22.152 +void Quaternion::rotate(const Quaternion &q)
  22.153 +{
  22.154 +	*this = q * *this * q.conjugate();
  22.155 +}
  22.156 +
  22.157 +Matrix3x3 Quaternion::get_rotation_matrix() const
  22.158 +{
  22.159 +	return Matrix3x3(
  22.160 +			1.0 - 2.0 * v.y*v.y - 2.0 * v.z*v.z,	2.0 * v.x * v.y - 2.0 * s * v.z,		2.0 * v.z * v.x + 2.0 * s * v.y,
  22.161 +			2.0 * v.x * v.y + 2.0 * s * v.z,		1.0 - 2.0 * v.x*v.x - 2.0 * v.z*v.z,	2.0 * v.y * v.z - 2.0 * s * v.x,
  22.162 +			2.0 * v.z * v.x - 2.0 * s * v.y,		2.0 * v.y * v.z + 2.0 * s * v.x,		1.0 - 2.0 * v.x*v.x - 2.0 * v.y*v.y);
  22.163 +}
  22.164 +
  22.165 +
  22.166 +/** Spherical linear interpolation (slerp) */
  22.167 +Quaternion slerp(const Quaternion &quat1, const Quaternion &q2, scalar_t t)
  22.168 +{
  22.169 +	Quaternion q1;
  22.170 +	scalar_t dot = q1.s * q2.s + q1.v.x * q2.v.x + q1.v.y * q2.v.y + q1.v.z * q2.v.z;
  22.171 +
  22.172 +	if(dot < 0.0) {
  22.173 +		/* make sure we interpolate across the shortest arc */
  22.174 +		q1 = -quat1;
  22.175 +		dot = -dot;
  22.176 +	} else {
  22.177 +		q1 = quat1;
  22.178 +	}
  22.179 +
  22.180 +	/* clamp dot to [-1, 1] in order to avoid domain errors in acos due to
  22.181 +	 * floating point imprecisions
  22.182 +	 */
  22.183 +	if(dot < -1.0) dot = -1.0;
  22.184 +	if(dot > 1.0) dot = 1.0;
  22.185 +
  22.186 +	scalar_t angle = acos(dot);
  22.187 +	scalar_t a, b;
  22.188 +
  22.189 +	scalar_t sin_angle = sin(angle);
  22.190 +	if(fabs(sin_angle) < SMALL_NUMBER) {
  22.191 +		/* for very small angles or completely opposite orientations
  22.192 +		 * use linear interpolation to avoid div/zero (in the first case it makes sense,
  22.193 +		 * the second case is pretty much undefined anyway I guess ...
  22.194 +		 */
  22.195 +		a = 1.0f - t;
  22.196 +		b = t;
  22.197 +	} else {
  22.198 +		a = sin((1.0f - t) * angle) / sin_angle;
  22.199 +		b = sin(t * angle) / sin_angle;
  22.200 +	}
  22.201 +
  22.202 +	scalar_t x = q1.v.x * a + q2.v.x * b;
  22.203 +	scalar_t y = q1.v.y * a + q2.v.y * b;
  22.204 +	scalar_t z = q1.v.z * a + q2.v.z * b;
  22.205 +	scalar_t s = q1.s * a + q2.s * b;
  22.206 +
  22.207 +	return Quaternion(s, Vector3(x, y, z));
  22.208 +}
  22.209 +
  22.210 +
  22.211 +std::ostream &operator <<(std::ostream &out, const Quaternion &q)
  22.212 +{
  22.213 +	out << "(" << q.s << ", " << q.v << ")";
  22.214 +	return out;
  22.215 +}
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/libs/vmath/quat.h	Sun Sep 29 08:20:19 2013 +0300
    23.3 @@ -0,0 +1,118 @@
    23.4 +/*
    23.5 +libvmath - a vector math library
    23.6 +Copyright (C) 2004-2011 John Tsiombikas <nuclear@member.fsf.org>
    23.7 +
    23.8 +This program is free software: you can redistribute it and/or modify
    23.9 +it under the terms of the GNU Lesser General Public License as published
   23.10 +by the Free Software Foundation, either version 3 of the License, or
   23.11 +(at your option) any later version.
   23.12 +
   23.13 +This program is distributed in the hope that it will be useful,
   23.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   23.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   23.16 +GNU Lesser General Public License for more details.
   23.17 +
   23.18 +You should have received a copy of the GNU Lesser General Public License
   23.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
   23.20 +*/
   23.21 +
   23.22 +#ifndef VMATH_QUATERNION_H_
   23.23 +#define VMATH_QUATERNION_H_
   23.24 +
   23.25 +#include <stdio.h>
   23.26 +#include "vmath_types.h"
   23.27 +#include "vector.h"
   23.28 +
   23.29 +#ifdef __cplusplus
   23.30 +extern "C" {
   23.31 +#endif	/* __cplusplus */
   23.32 +
   23.33 +#define quat_cons(s, x, y, z)	v4_cons(x, y, z, s)
   23.34 +#define quat_vec(q)				v3_cons((q).x, (q).y, (q).z)
   23.35 +#define quat_s(q)				((q).w)
   23.36 +#define quat_identity()			quat_cons(1.0, 0.0, 0.0, 0.0)
   23.37 +void quat_print(FILE *fp, quat_t q);
   23.38 +
   23.39 +#define quat_add		v4_add
   23.40 +#define quat_sub		v4_sub
   23.41 +#define quat_neg		v4_neg
   23.42 +
   23.43 +static inline quat_t quat_mul(quat_t q1, quat_t q2);
   23.44 +
   23.45 +static inline quat_t quat_conjugate(quat_t q);
   23.46 +
   23.47 +#define quat_length		v4_length
   23.48 +#define quat_length_sq	v4_length_sq
   23.49 +
   23.50 +#define quat_normalize	v4_normalize
   23.51 +static inline quat_t quat_inverse(quat_t q);
   23.52 +
   23.53 +quat_t quat_rotate(quat_t q, scalar_t angle, scalar_t x, scalar_t y, scalar_t z);
   23.54 +quat_t quat_rotate_quat(quat_t q, quat_t rotq);
   23.55 +
   23.56 +static inline void quat_to_mat3(mat3_t res, quat_t q);
   23.57 +static inline void quat_to_mat4(mat4_t res, quat_t q);
   23.58 +
   23.59 +#define quat_lerp quat_slerp
   23.60 +quat_t quat_slerp(quat_t q1, quat_t q2, scalar_t t);
   23.61 +
   23.62 +
   23.63 +#ifdef __cplusplus
   23.64 +}	/* extern "C" */
   23.65 +
   23.66 +#include <iostream>
   23.67 +
   23.68 +/* Quaternion */
   23.69 +class Quaternion {
   23.70 +public:
   23.71 +	scalar_t s;
   23.72 +	Vector3 v;
   23.73 +
   23.74 +	Quaternion();
   23.75 +	Quaternion(scalar_t s, const Vector3 &v);
   23.76 +	Quaternion(scalar_t s, scalar_t x, scalar_t y, scalar_t z);
   23.77 +	Quaternion(const Vector3 &axis, scalar_t angle);
   23.78 +	Quaternion(const quat_t &quat);
   23.79 +
   23.80 +	Quaternion operator +(const Quaternion &quat) const;
   23.81 +	Quaternion operator -(const Quaternion &quat) const;
   23.82 +	Quaternion operator -() const;
   23.83 +	Quaternion operator *(const Quaternion &quat) const;
   23.84 +
   23.85 +	void operator +=(const Quaternion &quat);
   23.86 +	void operator -=(const Quaternion &quat);
   23.87 +	void operator *=(const Quaternion &quat);
   23.88 +
   23.89 +	void reset_identity();
   23.90 +
   23.91 +	Quaternion conjugate() const;
   23.92 +
   23.93 +	scalar_t length() const;
   23.94 +	scalar_t length_sq() const;
   23.95 +
   23.96 +	void normalize();
   23.97 +	Quaternion normalized() const;
   23.98 +
   23.99 +	Quaternion inverse() const;
  23.100 +
  23.101 +	void set_rotation(const Vector3 &axis, scalar_t angle);
  23.102 +	void rotate(const Vector3 &axis, scalar_t angle);
  23.103 +	/* note: this is a totally different operation from the above
  23.104 +	 * this treats the quaternion as signifying direction and rotates
  23.105 +	 * it by a rotation quaternion by rot * q * rot'
  23.106 +	 */
  23.107 +	void rotate(const Quaternion &q);
  23.108 +
  23.109 +	Matrix3x3 get_rotation_matrix() const;
  23.110 +};
  23.111 +
  23.112 +Quaternion slerp(const Quaternion &q1, const Quaternion &q2, scalar_t t);
  23.113 +inline Quaternion lerp(const Quaternion &q1, const Quaternion &q2, scalar_t t);
  23.114 +
  23.115 +std::ostream &operator <<(std::ostream &out, const Quaternion &q);
  23.116 +
  23.117 +#endif	/* __cplusplus */
  23.118 +
  23.119 +#include "quat.inl"
  23.120 +
  23.121 +#endif	/* VMATH_QUATERNION_H_ */
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/libs/vmath/quat.inl	Sun Sep 29 08:20:19 2013 +0300
    24.3 @@ -0,0 +1,81 @@
    24.4 +/*
    24.5 +libvmath - a vector math library
    24.6 +Copyright (C) 2004-2011 John Tsiombikas <nuclear@member.fsf.org>
    24.7 +
    24.8 +This program is free software: you can redistribute it and/or modify
    24.9 +it under the terms of the GNU Lesser General Public License as published
   24.10 +by the Free Software Foundation, either version 3 of the License, or
   24.11 +(at your option) any later version.
   24.12 +
   24.13 +This program is distributed in the hope that it will be useful,
   24.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   24.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   24.16 +GNU Lesser General Public License for more details.
   24.17 +
   24.18 +You should have received a copy of the GNU Lesser General Public License
   24.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
   24.20 +*/
   24.21 +
   24.22 +#include "vector.h"
   24.23 +#include "matrix.h"
   24.24 +
   24.25 +#ifdef __cplusplus
   24.26 +extern "C" {
   24.27 +#endif	/* __cplusplus */
   24.28 +
   24.29 +static inline quat_t quat_mul(quat_t q1, quat_t q2)
   24.30 +{
   24.31 +	quat_t res;
   24.32 +	vec3_t v1 = quat_vec(q1);
   24.33 +	vec3_t v2 = quat_vec(q2);
   24.34 +
   24.35 +	res.w = q1.w * q2.w - v3_dot(v1, v2);
   24.36 +	/* resvec = v2 * q1 + v1 * q2 + cross(v1, v2) */
   24.37 +	res.x = v2.x * q1.w + v1.x * q2.w + (v1.y * v2.z - v1.z * v2.y);
   24.38 +	res.y = v2.y * q1.w + v1.y * q2.w + (v1.z * v2.x - v1.x * v2.z);
   24.39 +	res.z = v2.z * q1.w + v1.z * q2.w + (v1.x * v2.y - v1.y * v2.x);
   24.40 +	return res;
   24.41 +}
   24.42 +
   24.43 +static inline quat_t quat_conjugate(quat_t q)
   24.44 +{
   24.45 +	q.x = -q.x;
   24.46 +	q.y = -q.y;
   24.47 +	q.z = -q.z;
   24.48 +	return q;
   24.49 +}
   24.50 +
   24.51 +static inline quat_t quat_inverse(quat_t q)
   24.52 +{
   24.53 +	scalar_t lensq = quat_length_sq(q);
   24.54 +	q = quat_conjugate(q);
   24.55 +	q.x /= lensq;
   24.56 +	q.y /= lensq;
   24.57 +	q.z /= lensq;
   24.58 +	q.w /= lensq;
   24.59 +	return q;
   24.60 +}
   24.61 +
   24.62 +static inline void quat_to_mat3(mat3_t res, quat_t q)
   24.63 +{
   24.64 +	m3_cons(res, 1.0 - 2.0 * q.y*q.y - 2.0 * q.z*q.z, 2.0 * q.x * q.y - 2.0 * q.w * q.z,   2.0 * q.z * q.x + 2.0 * q.w * q.y,
   24.65 +				 2.0 * q.x * q.y + 2.0 * q.w * q.z,   1.0 - 2.0 * q.x*q.x - 2.0 * q.z*q.z, 2.0 * q.y * q.z - 2.0 * q.w * q.x,
   24.66 +				 2.0 * q.z * q.x - 2.0 * q.w * q.y,   2.0 * q.y * q.z + 2.0 * q.w * q.x,   1.0 - 2.0 * q.x*q.x - 2.0 * q.y*q.y);
   24.67 +}
   24.68 +
   24.69 +static inline void quat_to_mat4(mat4_t res, quat_t q)
   24.70 +{
   24.71 +	m4_cons(res, 1.0 - 2.0 * q.y*q.y - 2.0 * q.z*q.z, 2.0 * q.x * q.y - 2.0 * q.w * q.z,   2.0 * q.z * q.x + 2.0 * q.w * q.y,   0,
   24.72 +				 2.0 * q.x * q.y + 2.0 * q.w * q.z,   1.0 - 2.0 * q.x*q.x - 2.0 * q.z*q.z, 2.0 * q.y * q.z - 2.0 * q.w * q.x,   0,
   24.73 +				 2.0 * q.z * q.x - 2.0 * q.w * q.y,   2.0 * q.y * q.z + 2.0 * q.w * q.x,   1.0 - 2.0 * q.x*q.x - 2.0 * q.y*q.y, 0,
   24.74 +				 0, 0, 0, 1);
   24.75 +}
   24.76 +
   24.77 +#ifdef __cplusplus
   24.78 +}	/* extern "C" */
   24.79 +
   24.80 +inline Quaternion lerp(const Quaternion &a, const Quaternion &b, scalar_t t)
   24.81 +{
   24.82 +	return slerp(a, b, t);
   24.83 +}
   24.84 +#endif	/* __cplusplus */
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/libs/vmath/quat_c.c	Sun Sep 29 08:20:19 2013 +0300
    25.3 @@ -0,0 +1,89 @@
    25.4 +/*
    25.5 +libvmath - a vector math library
    25.6 +Copyright (C) 2004-2011 John Tsiombikas <nuclear@member.fsf.org>
    25.7 +
    25.8 +This program is free software: you can redistribute it and/or modify
    25.9 +it under the terms of the GNU Lesser General Public License as published
   25.10 +by the Free Software Foundation, either version 3 of the License, or
   25.11 +(at your option) any later version.
   25.12 +
   25.13 +This program is distributed in the hope that it will be useful,
   25.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   25.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   25.16 +GNU Lesser General Public License for more details.
   25.17 +
   25.18 +You should have received a copy of the GNU Lesser General Public License
   25.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
   25.20 +*/
   25.21 +
   25.22 +
   25.23 +#include <stdio.h>
   25.24 +#include <math.h>
   25.25 +#include "quat.h"
   25.26 +
   25.27 +void quat_print(FILE *fp, quat_t q)
   25.28 +{
   25.29 +	fprintf(fp, "([ %.4f %.4f %.4f ] %.4f)", q.x, q.y, q.z, q.w);
   25.30 +}
   25.31 +
   25.32 +quat_t quat_rotate(quat_t q, scalar_t angle, scalar_t x, scalar_t y, scalar_t z)
   25.33 +{
   25.34 +	quat_t rq;
   25.35 +	scalar_t half_angle = angle * 0.5;
   25.36 +	scalar_t sin_half = sin(half_angle);
   25.37 +
   25.38 +	rq.w = cos(half_angle);
   25.39 +	rq.x = x * sin_half;
   25.40 +	rq.y = y * sin_half;
   25.41 +	rq.z = z * sin_half;
   25.42 +
   25.43 +	return quat_mul(q, rq);
   25.44 +}
   25.45 +
   25.46 +quat_t quat_rotate_quat(quat_t q, quat_t rotq)
   25.47 +{
   25.48 +	return quat_mul(quat_mul(rotq, q), quat_conjugate(rotq));
   25.49 +}
   25.50 +
   25.51 +quat_t quat_slerp(quat_t q1, quat_t q2, scalar_t t)
   25.52 +{
   25.53 +	quat_t res;
   25.54 +	scalar_t a, b, angle, sin_angle, dot;
   25.55 +
   25.56 +	dot = q1.w * q2.w + q1.x * q2.x + q1.y * q2.y + q1.z * q2.z;
   25.57 +	if(dot < 0.0) {
   25.58 +		/* make sure we interpolate across the shortest arc */
   25.59 +		q1.x = -q1.x;
   25.60 +		q1.y = -q1.y;
   25.61 +		q1.z = -q1.z;
   25.62 +		q1.w = -q1.w;
   25.63 +		dot = -dot;
   25.64 +	}
   25.65 +
   25.66 +	/* clamp dot to [-1, 1] in order to avoid domain errors in acos due to
   25.67 +	 * floating point imprecisions
   25.68 +	 */
   25.69 +	if(dot < -1.0) dot = -1.0;
   25.70 +	if(dot > 1.0) dot = 1.0;
   25.71 +
   25.72 +	angle = acos(dot);
   25.73 +	sin_angle = sin(angle);
   25.74 +
   25.75 +	if(fabs(sin_angle) < SMALL_NUMBER) {
   25.76 +		/* for very small angles or completely opposite orientations
   25.77 +		 * use linear interpolation to avoid div/zero (in the first case it makes sense,
   25.78 +		 * the second case is pretty much undefined anyway I guess ...
   25.79 +		 */
   25.80 +		a = 1.0f - t;
   25.81 +		b = t;
   25.82 +	} else {
   25.83 +		a = sin((1.0f - t) * angle) / sin_angle;
   25.84 +		b = sin(t * angle) / sin_angle;
   25.85 +	}
   25.86 +
   25.87 +	res.x = q1.x * a + q2.x * b;
   25.88 +	res.y = q1.y * a + q2.y * b;
   25.89 +	res.z = q1.z * a + q2.z * b;
   25.90 +	res.w = q1.w * a + q2.w * b;
   25.91 +	return res;
   25.92 +}
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/libs/vmath/ray.cc	Sun Sep 29 08:20:19 2013 +0300
    26.3 @@ -0,0 +1,39 @@
    26.4 +#include "ray.h"
    26.5 +#include "vector.h"
    26.6 +
    26.7 +scalar_t Ray::env_ior = 1.0;
    26.8 +
    26.9 +Ray::Ray()
   26.10 +{
   26.11 +	ior = env_ior;
   26.12 +	energy = 1.0;
   26.13 +	time = 0;
   26.14 +	iter = 0;
   26.15 +}
   26.16 +
   26.17 +Ray::Ray(const Vector3 &origin, const Vector3 &dir)
   26.18 +{
   26.19 +	this->origin = origin;
   26.20 +	this->dir = dir;
   26.21 +	ior = env_ior;
   26.22 +	energy = 1.0;
   26.23 +	time = 0;
   26.24 +	iter = 0;
   26.25 +}
   26.26 +
   26.27 +void Ray::transform(const Matrix4x4 &xform)
   26.28 +{
   26.29 +	Matrix4x4 upper = xform;
   26.30 +	upper[0][3] = upper[1][3] = upper[2][3] = upper[3][0] = upper[3][1] = upper[3][2] = 0.0;
   26.31 +	upper[3][3] = 1.0;
   26.32 +
   26.33 +	dir.transform(upper);
   26.34 +	origin.transform(xform);
   26.35 +}
   26.36 +
   26.37 +Ray Ray::transformed(const Matrix4x4 &xform) const
   26.38 +{
   26.39 +	Ray foo = *this;
   26.40 +	foo.transform(xform);
   26.41 +	return foo;
   26.42 +}
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/libs/vmath/ray.h	Sun Sep 29 08:20:19 2013 +0300
    27.3 @@ -0,0 +1,64 @@
    27.4 +/*
    27.5 +libvmath - a vector math library
    27.6 +Copyright (C) 2004-2011 John Tsiombikas <nuclear@member.fsf.org>
    27.7 +
    27.8 +This program is free software: you can redistribute it and/or modify
    27.9 +it under the terms of the GNU Lesser General Public License as published
   27.10 +by the Free Software Foundation, either version 3 of the License, or
   27.11 +(at your option) any later version.
   27.12 +
   27.13 +This program is distributed in the hope that it will be useful,
   27.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   27.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   27.16 +GNU Lesser General Public License for more details.
   27.17 +
   27.18 +You should have received a copy of the GNU Lesser General Public License
   27.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
   27.20 +*/
   27.21 +
   27.22 +#ifndef VMATH_RAY_H_
   27.23 +#define VMATH_RAY_H_
   27.24 +
   27.25 +#include "matrix.h"
   27.26 +#include "vector.h"
   27.27 +
   27.28 +typedef struct {
   27.29 +	vec3_t origin, dir;
   27.30 +} ray_t;
   27.31 +
   27.32 +#ifdef __cplusplus
   27.33 +extern "C" {
   27.34 +#endif	/* __cplusplus */
   27.35 +
   27.36 +static inline ray_t ray_cons(vec3_t origin, vec3_t dir);
   27.37 +ray_t ray_transform(ray_t r, mat4_t m);
   27.38 +
   27.39 +#ifdef __cplusplus
   27.40 +}	/* __cplusplus */
   27.41 +
   27.42 +#include <stack>
   27.43 +
   27.44 +class Ray {
   27.45 +public:
   27.46 +	static scalar_t env_ior;
   27.47 +
   27.48 +	Vector3 origin, dir;
   27.49 +	scalar_t energy;
   27.50 +	int iter;
   27.51 +	scalar_t ior;
   27.52 +	long time;
   27.53 +
   27.54 +	Ray();
   27.55 +	Ray(const Vector3 &origin, const Vector3 &dir);
   27.56 +
   27.57 +	void transform(const Matrix4x4 &xform);
   27.58 +	Ray transformed(const Matrix4x4 &xform) const;
   27.59 +};
   27.60 +
   27.61 +inline Ray reflect_ray(const Ray &inray, const Vector3 &norm);
   27.62 +inline Ray refract_ray(const Ray &inray, const Vector3 &norm, scalar_t from_ior, scalar_t to_ior);
   27.63 +#endif	/* __cplusplus */
   27.64 +
   27.65 +#include "ray.inl"
   27.66 +
   27.67 +#endif	/* VMATH_RAY_H_ */
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/libs/vmath/ray.inl	Sun Sep 29 08:20:19 2013 +0300
    28.3 @@ -0,0 +1,52 @@
    28.4 +/*
    28.5 +libvmath - a vector math library
    28.6 +Copyright (C) 2004-2011 John Tsiombikas <nuclear@member.fsf.org>
    28.7 +
    28.8 +This program is free software: you can redistribute it and/or modify
    28.9 +it under the terms of the GNU Lesser General Public License as published
   28.10 +by the Free Software Foundation, either version 3 of the License, or
   28.11 +(at your option) any later version.
   28.12 +
   28.13 +This program is distributed in the hope that it will be useful,
   28.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   28.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   28.16 +GNU Lesser General Public License for more details.
   28.17 +
   28.18 +You should have received a copy of the GNU Lesser General Public License
   28.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
   28.20 +*/
   28.21 +
   28.22 +#ifdef __cplusplus
   28.23 +extern "C" {
   28.24 +#endif	/* __cplusplus */
   28.25 +
   28.26 +static inline ray_t ray_cons(vec3_t origin, vec3_t dir)
   28.27 +{
   28.28 +	ray_t r;
   28.29 +	r.origin = origin;
   28.30 +	r.dir = dir;
   28.31 +	return r;
   28.32 +}
   28.33 +
   28.34 +#ifdef __cplusplus
   28.35 +}
   28.36 +
   28.37 +inline Ray reflect_ray(const Ray &inray, const Vector3 &norm)
   28.38 +{
   28.39 +	Ray ray = inray;
   28.40 +	ray.dir = ray.dir.reflection(norm);
   28.41 +	return ray;
   28.42 +}
   28.43 +
   28.44 +inline Ray refract_ray(const Ray &inray, const Vector3 &norm, scalar_t from_ior, scalar_t to_ior)
   28.45 +{
   28.46 +	Ray ray = inray;
   28.47 +	ray.dir = ray.dir.refraction(norm, from_ior, to_ior);
   28.48 +
   28.49 +	/* check TIR */
   28.50 +	if(dot_product(ray.dir, norm) > 0.0) {
   28.51 +		return reflect_ray(inray, norm);
   28.52 +	}
   28.53 +	return ray;
   28.54 +}
   28.55 +#endif	/* __cplusplus */
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/libs/vmath/ray_c.c	Sun Sep 29 08:20:19 2013 +0300
    29.3 @@ -0,0 +1,36 @@
    29.4 +/*
    29.5 +libvmath - a vector math library
    29.6 +Copyright (C) 2004-2011 John Tsiombikas <nuclear@member.fsf.org>
    29.7 +
    29.8 +This program is free software: you can redistribute it and/or modify
    29.9 +it under the terms of the GNU Lesser General Public License as published
   29.10 +by the Free Software Foundation, either version 3 of the License, or
   29.11 +(at your option) any later version.
   29.12 +
   29.13 +This program is distributed in the hope that it will be useful,
   29.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   29.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   29.16 +GNU Lesser General Public License for more details.
   29.17 +
   29.18 +You should have received a copy of the GNU Lesser General Public License
   29.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
   29.20 +*/
   29.21 +
   29.22 +#include "ray.h"
   29.23 +#include "vector.h"
   29.24 +
   29.25 +ray_t ray_transform(ray_t r, mat4_t xform)
   29.26 +{
   29.27 +	mat4_t upper;
   29.28 +	vec3_t dir;
   29.29 +
   29.30 +	m4_copy(upper, xform);
   29.31 +	upper[0][3] = upper[1][3] = upper[2][3] = upper[3][0] = upper[3][1] = upper[3][2] = 0.0;
   29.32 +	upper[3][3] = 1.0;
   29.33 +
   29.34 +	dir = v3_sub(r.dir, r.origin);
   29.35 +	dir = v3_transform(dir, upper);
   29.36 +	r.origin = v3_transform(r.origin, xform);
   29.37 +	r.dir = v3_add(dir, r.origin);
   29.38 +	return r;
   29.39 +}
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/libs/vmath/sphvec.cc	Sun Sep 29 08:20:19 2013 +0300
    30.3 @@ -0,0 +1,27 @@
    30.4 +#include "sphvec.h"
    30.5 +#include "vector.h"
    30.6 +
    30.7 +/* theta: 0 <= theta <= 2pi, the angle around Y axis.
    30.8 + * phi: 0 <= phi <= pi, the angle from Y axis.
    30.9 + * r: radius.
   30.10 + */
   30.11 +SphVector::SphVector(scalar_t theta, scalar_t phi, scalar_t r) {
   30.12 +	this->theta = theta;
   30.13 +	this->phi = phi;
   30.14 +	this->r = r;
   30.15 +}
   30.16 +
   30.17 +/* Constructs a spherical coordinate vector from a cartesian vector */
   30.18 +SphVector::SphVector(const Vector3 &cvec) {
   30.19 +	*this = cvec;
   30.20 +}
   30.21 +
   30.22 +/* Assignment operator that converts cartesian to spherical coords */
   30.23 +SphVector &SphVector::operator =(const Vector3 &cvec) {
   30.24 +	r = cvec.length();
   30.25 +	//theta = atan2(cvec.y, cvec.x);
   30.26 +	theta = atan2(cvec.z, cvec.x);
   30.27 +	//phi = acos(cvec.z / r);
   30.28 +	phi = acos(cvec.y / r);
   30.29 +	return *this;
   30.30 +}
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/libs/vmath/sphvec.h	Sun Sep 29 08:20:19 2013 +0300
    31.3 @@ -0,0 +1,36 @@
    31.4 +/*
    31.5 +libvmath - a vector math library
    31.6 +Copyright (C) 2004-2011 John Tsiombikas <nuclear@member.fsf.org>
    31.7 +
    31.8 +This program is free software: you can redistribute it and/or modify
    31.9 +it under the terms of the GNU Lesser General Public License as published
   31.10 +by the Free Software Foundation, either version 3 of the License, or
   31.11 +(at your option) any later version.
   31.12 +
   31.13 +This program is distributed in the hope that it will be useful,
   31.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   31.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   31.16 +GNU Lesser General Public License for more details.
   31.17 +
   31.18 +You should have received a copy of the GNU Lesser General Public License
   31.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
   31.20 +*/
   31.21 +
   31.22 +#ifndef VMATH_SPHVEC_H_
   31.23 +#define VMATH_SPHVEC_H_
   31.24 +
   31.25 +#include "vmath_types.h"
   31.26 +
   31.27 +#ifdef __cplusplus
   31.28 +/* Vector in spherical coordinates */
   31.29 +class SphVector {
   31.30 +public:
   31.31 +	scalar_t theta, phi, r;
   31.32 +
   31.33 +	SphVector(scalar_t theta = 0.0, scalar_t phi = 0.0, scalar_t r = 1.0);
   31.34 +	SphVector(const Vector3 &cvec);
   31.35 +	SphVector &operator =(const Vector3 &cvec);
   31.36 +};
   31.37 +#endif	/* __cplusplus */
   31.38 +
   31.39 +#endif	/* VMATH_SPHVEC_H_ */
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/libs/vmath/vector.cc	Sun Sep 29 08:20:19 2013 +0300
    32.3 @@ -0,0 +1,326 @@
    32.4 +#include "vector.h"
    32.5 +#include "vmath.h"
    32.6 +
    32.7 +// ---------- Vector2 -----------
    32.8 +
    32.9 +Vector2::Vector2(scalar_t x, scalar_t y)
   32.10 +{
   32.11 +	this->x = x;
   32.12 +	this->y = y;
   32.13 +}
   32.14 +
   32.15 +Vector2::Vector2(const vec2_t &vec)
   32.16 +{
   32.17 +	x = vec.x;
   32.18 +	y = vec.y;
   32.19 +}
   32.20 +
   32.21 +Vector2::Vector2(const Vector3 &vec)
   32.22 +{
   32.23 +	x = vec.x;
   32.24 +	y = vec.y;
   32.25 +}
   32.26 +
   32.27 +Vector2::Vector2(const Vector4 &vec)
   32.28 +{
   32.29 +	x = vec.x;
   32.30 +	y = vec.y;
   32.31 +}
   32.32 +
   32.33 +void Vector2::normalize()
   32.34 +{
   32.35 +	scalar_t len = length();
   32.36 +	x /= len;
   32.37 +	y /= len;
   32.38 +}
   32.39 +
   32.40 +Vector2 Vector2::normalized() const
   32.41 +{
   32.42 +	scalar_t len = length();
   32.43 +	return Vector2(x / len, y / len);
   32.44 +}
   32.45 +
   32.46 +void Vector2::transform(const Matrix3x3 &mat)
   32.47 +{
   32.48 +	scalar_t nx = mat[0][0] * x + mat[0][1] * y + mat[0][2];
   32.49 +	y = mat[1][0] * x + mat[1][1] * y + mat[1][2];
   32.50 +	x = nx;
   32.51 +}
   32.52 +
   32.53 +Vector2 Vector2::transformed(const Matrix3x3 &mat) const
   32.54 +{
   32.55 +	Vector2 vec;
   32.56 +	vec.x = mat[0][0] * x + mat[0][1] * y + mat[0][2];
   32.57 +	vec.y = mat[1][0] * x + mat[1][1] * y + mat[1][2];
   32.58 +	return vec;
   32.59 +}
   32.60 +
   32.61 +void Vector2::rotate(scalar_t angle)
   32.62 +{
   32.63 +	*this = Vector2(cos(angle) * x - sin(angle) * y, sin(angle) * x + cos(angle) * y);
   32.64 +}
   32.65 +
   32.66 +Vector2 Vector2::rotated(scalar_t angle) const
   32.67 +{
   32.68 +	return Vector2(cos(angle) * x - sin(angle) * y, sin(angle) * x + cos(angle) * y);
   32.69 +}
   32.70 +
   32.71 +Vector2 Vector2::reflection(const Vector2 &normal) const
   32.72 +{
   32.73 +	return 2.0 * dot_product(*this, normal) * normal - *this;
   32.74 +}
   32.75 +
   32.76 +Vector2 Vector2::refraction(const Vector2 &normal, scalar_t src_ior, scalar_t dst_ior) const
   32.77 +{
   32.78 +	// quick and dirty implementation :)
   32.79 +	Vector3 v3refr = Vector3(this->x, this->y, 1.0).refraction(Vector3(this->x, this->y, 1), src_ior, dst_ior);
   32.80 +	return Vector2(v3refr.x, v3refr.y);
   32.81 +}
   32.82 +
   32.83 +std::ostream &operator <<(std::ostream &out, const Vector2 &vec)
   32.84 +{
   32.85 +	out << "[" << vec.x << " " << vec.y << "]";
   32.86 +	return out;
   32.87 +}
   32.88 +
   32.89 +
   32.90 +
   32.91 +// --------- Vector3 ----------
   32.92 +
   32.93 +Vector3::Vector3(scalar_t x, scalar_t y, scalar_t z)
   32.94 +{
   32.95 +	this->x = x;
   32.96 +	this->y = y;
   32.97 +	this->z = z;
   32.98 +}
   32.99 +
  32.100 +Vector3::Vector3(const vec3_t &vec)
  32.101 +{
  32.102 +	x = vec.x;
  32.103 +	y = vec.y;
  32.104 +	z = vec.z;
  32.105 +}
  32.106 +
  32.107 +Vector3::Vector3(const Vector2 &vec)
  32.108 +{
  32.109 +	x = vec.x;
  32.110 +	y = vec.y;
  32.111 +	z = 1;
  32.112 +}
  32.113 +
  32.114 +Vector3::Vector3(const Vector4 &vec)
  32.115 +{
  32.116 +	x = vec.x;
  32.117 +	y = vec.y;
  32.118 +	z = vec.z;
  32.119 +}
  32.120 +
  32.121 +Vector3::Vector3(const SphVector &sph)
  32.122 +{
  32.123 +	*this = sph;
  32.124 +}
  32.125 +
  32.126 +Vector3 &Vector3::operator =(const SphVector &sph)
  32.127 +{
  32.128 +	x = sph.r * cos(sph.theta) * sin(sph.phi);
  32.129 +	z = sph.r * sin(sph.theta) * sin(sph.phi);
  32.130 +	y = sph.r * cos(sph.phi);
  32.131 +	return *this;
  32.132 +}
  32.133 +
  32.134 +void Vector3::normalize()
  32.135 +{
  32.136 +	scalar_t len = length();
  32.137 +	x /= len;
  32.138 +	y /= len;
  32.139 +	z /= len;
  32.140 +}
  32.141 +
  32.142 +Vector3 Vector3::normalized() const
  32.143 +{
  32.144 +	scalar_t len = length();
  32.145 +	return Vector3(x / len, y / len, z / len);
  32.146 +}
  32.147 +
  32.148 +Vector3 Vector3::reflection(const Vector3 &normal) const
  32.149 +{
  32.150 +	return 2.0 * dot_product(*this, normal) * normal - *this;
  32.151 +}
  32.152 +
  32.153 +Vector3 Vector3::refraction(const Vector3 &normal, scalar_t src_ior, scalar_t dst_ior) const
  32.154 +{
  32.155 +	return refraction(normal, src_ior / dst_ior);
  32.156 +}
  32.157 +
  32.158 +Vector3 Vector3::refraction(const Vector3 &normal, scalar_t ior) const
  32.159 +{
  32.160 +	scalar_t cos_inc = dot_product(*this, -normal);
  32.161 +
  32.162 +	scalar_t radical = 1.0 + SQ(ior) * (SQ(cos_inc) - 1.0);
  32.163 +
  32.164 +	if(radical < 0.0) {		// total internal reflection
  32.165 +		return -reflection(normal);
  32.166 +	}
  32.167 +
  32.168 +	scalar_t beta = ior * cos_inc - sqrt(radical);
  32.169 +
  32.170 +	return *this * ior + normal * beta;
  32.171 +}
  32.172 +
  32.173 +void Vector3::transform(const Matrix3x3 &mat)
  32.174 +{
  32.175 +	scalar_t nx = mat[0][0] * x + mat[0][1] * y + mat[0][2] * z;
  32.176 +	scalar_t ny = mat[1][0] * x + mat[1][1] * y + mat[1][2] * z;
  32.177 +	z = mat[2][0] * x + mat[2][1] * y + mat[2][2] * z;
  32.178 +	x = nx;
  32.179 +	y = ny;
  32.180 +}
  32.181 +
  32.182 +Vector3 Vector3::transformed(const Matrix3x3 &mat) const
  32.183 +{
  32.184 +	Vector3 vec;
  32.185 +	vec.x = mat[0][0] * x + mat[0][1] * y + mat[0][2] * z;
  32.186 +	vec.y = mat[1][0] * x + mat[1][1] * y + mat[1][2] * z;
  32.187 +	vec.z = mat[2][0] * x + mat[2][1] * y + mat[2][2] * z;
  32.188 +	return vec;
  32.189 +}
  32.190 +
  32.191 +void Vector3::transform(const Matrix4x4 &mat)
  32.192 +{
  32.193 +	scalar_t nx = mat[0][0] * x + mat[0][1] * y + mat[0][2] * z + mat[0][3];
  32.194 +	scalar_t ny = mat[1][0] * x + mat[1][1] * y + mat[1][2] * z + mat[1][3];
  32.195 +	z = mat[2][0] * x + mat[2][1] * y + mat[2][2] * z + mat[2][3];
  32.196 +	x = nx;
  32.197 +	y = ny;
  32.198 +}
  32.199 +
  32.200 +Vector3 Vector3::transformed(const Matrix4x4 &mat) const
  32.201 +{
  32.202 +	Vector3 vec;
  32.203 +	vec.x = mat[0][0] * x + mat[0][1] * y + mat[0][2] * z + mat[0][3];
  32.204 +	vec.y = mat[1][0] * x + mat[1][1] * y + mat[1][2] * z + mat[1][3];
  32.205 +	vec.z = mat[2][0] * x + mat[2][1] * y + mat[2][2] * z + mat[2][3];
  32.206 +	return vec;
  32.207 +}
  32.208 +
  32.209 +void Vector3::transform(const Quaternion &quat)
  32.210 +{
  32.211 +	Quaternion vq(0.0f, *this);
  32.212 +	vq = quat * vq * quat.inverse();
  32.213 +	*this = vq.v;
  32.214 +}
  32.215 +
  32.216 +Vector3 Vector3::transformed(const Quaternion &quat) const
  32.217 +{
  32.218 +	Quaternion vq(0.0f, *this);
  32.219 +	vq = quat * vq * quat.inverse();
  32.220 +	return vq.v;
  32.221 +}
  32.222 +
  32.223 +void Vector3::rotate(const Vector3 &euler)
  32.224 +{
  32.225 +	Matrix4x4 rot;
  32.226 +	rot.set_rotation(euler);
  32.227 +	transform(rot);
  32.228 +}
  32.229 +
  32.230 +Vector3 Vector3::rotated(const Vector3 &euler) const
  32.231 +{
  32.232 +	Matrix4x4 rot;
  32.233 +	rot.set_rotation(euler);
  32.234 +	return transformed(rot);
  32.235 +}
  32.236 +
  32.237 +std::ostream &operator <<(std::ostream &out, const Vector3 &vec)
  32.238 +{
  32.239 +	out << "[" << vec.x << " " << vec.y << " " << vec.z << "]";
  32.240 +	return out;
  32.241 +}
  32.242 +
  32.243 +
  32.244 +// -------------- Vector4 --------------
  32.245 +Vector4::Vector4(scalar_t x, scalar_t y, scalar_t z, scalar_t w)
  32.246 +{
  32.247 +	this->x = x;
  32.248 +	this->y = y;
  32.249 +	this->z = z;
  32.250 +	this->w = w;
  32.251 +}
  32.252 +
  32.253 +Vector4::Vector4(const vec4_t &vec)
  32.254 +{
  32.255 +	x = vec.x;
  32.256 +	y = vec.y;
  32.257 +	z = vec.z;
  32.258 +	w = vec.w;
  32.259 +}
  32.260 +
  32.261 +Vector4::Vector4(const Vector2 &vec)
  32.262 +{
  32.263 +	x = vec.x;
  32.264 +	y = vec.y;
  32.265 +	z = 1;
  32.266 +	w = 1;
  32.267 +}
  32.268 +
  32.269 +Vector4::Vector4(const Vector3 &vec)
  32.270 +{
  32.271 +	x = vec.x;
  32.272 +	y = vec.y;
  32.273 +	z = vec.z;
  32.274 +	w = 1;
  32.275 +}
  32.276 +
  32.277 +void Vector4::normalize()
  32.278 +{
  32.279 +	scalar_t len = (scalar_t)sqrt(x*x + y*y + z*z + w*w);
  32.280 +	x /= len;
  32.281 +	y /= len;
  32.282 +	z /= len;
  32.283 +	w /= len;
  32.284 +}
  32.285 +
  32.286 +Vector4 Vector4::normalized() const
  32.287 +{
  32.288 +	scalar_t len = (scalar_t)sqrt(x*x + y*y + z*z + w*w);
  32.289 +	return Vector4(x / len, y / len, z / len, w / len);
  32.290 +}
  32.291 +
  32.292 +void Vector4::transform(const Matrix4x4 &mat)
  32.293 +{
  32.294 +	scalar_t nx = mat[0][0] * x + mat[0][1] * y + mat[0][2] * z + mat[0][3] * w;
  32.295 +	scalar_t ny = mat[1][0] * x + mat[1][1] * y + mat[1][2] * z + mat[1][3] * w;
  32.296 +	scalar_t nz = mat[2][0] * x + mat[2][1] * y + mat[2][2] * z + mat[2][3] * w;
  32.297 +	w = mat[3][0] * x + mat[3][1] * y + mat[3][2] * z + mat[3][3] * w;
  32.298 +	x = nx;
  32.299 +	y = ny;
  32.300 +	z = nz;
  32.301 +}
  32.302 +
  32.303 +Vector4 Vector4::transformed(const Matrix4x4 &mat) const
  32.304 +{
  32.305 +	Vector4 vec;
  32.306 +	vec.x = mat[0][0] * x + mat[0][1] * y + mat[0][2] * z + mat[0][3] * w;
  32.307 +	vec.y = mat[1][0] * x + mat[1][1] * y + mat[1][2] * z + mat[1][3] * w;
  32.308 +	vec.z = mat[2][0] * x + mat[2][1] * y + mat[2][2] * z + mat[2][3] * w;
  32.309 +	vec.w = mat[3][0] * x + mat[3][1] * y + mat[3][2] * z + mat[3][3] * w;
  32.310 +	return vec;
  32.311 +}
  32.312 +
  32.313 +// TODO: implement 4D vector reflection
  32.314 +Vector4 Vector4::reflection(const Vector4 &normal) const
  32.315 +{
  32.316 +	return *this;
  32.317 +}
  32.318 +
  32.319 +// TODO: implement 4D vector refraction
  32.320 +Vector4 Vector4::refraction(const Vector4 &normal, scalar_t src_ior, scalar_t dst_ior) const
  32.321 +{
  32.322 +	return *this;
  32.323 +}
  32.324 +
  32.325 +std::ostream &operator <<(std::ostream &out, const Vector4 &vec)
  32.326 +{
  32.327 +	out << "[" << vec.x << " " << vec.y << " " << vec.z << " " << vec.w << "]";
  32.328 +	return out;
  32.329 +}
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/libs/vmath/vector.h	Sun Sep 29 08:20:19 2013 +0300
    33.3 @@ -0,0 +1,292 @@
    33.4 +/*
    33.5 +libvmath - a vector math library
    33.6 +Copyright (C) 2004-2011 John Tsiombikas <nuclear@member.fsf.org>
    33.7 +
    33.8 +This program is free software: you can redistribute it and/or modify
    33.9 +it under the terms of the GNU Lesser General Public License as published
   33.10 +by the Free Software Foundation, either version 3 of the License, or
   33.11 +(at your option) any later version.
   33.12 +
   33.13 +This program is distributed in the hope that it will be useful,
   33.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   33.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   33.16 +GNU Lesser General Public License for more details.
   33.17 +
   33.18 +You should have received a copy of the GNU Lesser General Public License
   33.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
   33.20 +*/
   33.21 +
   33.22 +#ifndef VMATH_VECTOR_H_
   33.23 +#define VMATH_VECTOR_H_
   33.24 +
   33.25 +#include <stdio.h>
   33.26 +#include "vmath_types.h"
   33.27 +
   33.28 +#ifdef __cplusplus
   33.29 +extern "C" {
   33.30 +#endif	/* __cplusplus */
   33.31 +
   33.32 +/* C 2D vector functions */
   33.33 +static inline vec2_t v2_cons(scalar_t x, scalar_t y);
   33.34 +static inline void v2_print(FILE *fp, vec2_t v);
   33.35 +
   33.36 +static inline vec2_t v2_add(vec2_t v1, vec2_t v2);
   33.37 +static inline vec2_t v2_sub(vec2_t v1, vec2_t v2);
   33.38 +static inline vec2_t v2_scale(vec2_t v, scalar_t s);
   33.39 +static inline scalar_t v2_dot(vec2_t v1, vec2_t v2);
   33.40 +static inline scalar_t v2_length(vec2_t v);
   33.41 +static inline scalar_t v2_length_sq(vec2_t v);
   33.42 +static inline vec2_t v2_normalize(vec2_t v);
   33.43 +
   33.44 +static inline vec2_t v2_lerp(vec2_t v1, vec2_t v2, scalar_t t);
   33.45 +
   33.46 +/* C 3D vector functions */
   33.47 +static inline vec3_t v3_cons(scalar_t x, scalar_t y, scalar_t z);
   33.48 +static inline void v3_print(FILE *fp, vec3_t v);
   33.49 +
   33.50 +static inline vec3_t v3_add(vec3_t v1, vec3_t v2);
   33.51 +static inline vec3_t v3_sub(vec3_t v1, vec3_t v2);
   33.52 +static inline vec3_t v3_neg(vec3_t v);
   33.53 +static inline vec3_t v3_mul(vec3_t v1, vec3_t v2);
   33.54 +static inline vec3_t v3_scale(vec3_t v1, scalar_t s);
   33.55 +static inline scalar_t v3_dot(vec3_t v1, vec3_t v2);
   33.56 +static inline vec3_t v3_cross(vec3_t v1, vec3_t v2);
   33.57 +static inline scalar_t v3_length(vec3_t v);
   33.58 +static inline scalar_t v3_length_sq(vec3_t v);
   33.59 +static inline vec3_t v3_normalize(vec3_t v);
   33.60 +static inline vec3_t v3_transform(vec3_t v, mat4_t m);
   33.61 +
   33.62 +static inline vec3_t v3_rotate(vec3_t v, scalar_t x, scalar_t y, scalar_t z);
   33.63 +static inline vec3_t v3_rotate_axis(vec3_t v, scalar_t angle, scalar_t x, scalar_t y, scalar_t z);
   33.64 +static inline vec3_t v3_rotate_quat(vec3_t v, quat_t q);
   33.65 +
   33.66 +static inline vec3_t v3_reflect(vec3_t v, vec3_t n);
   33.67 +
   33.68 +static inline vec3_t v3_lerp(vec3_t v1, vec3_t v2, scalar_t t);
   33.69 +
   33.70 +/* C 4D vector functions */
   33.71 +static inline vec4_t v4_cons(scalar_t x, scalar_t y, scalar_t z, scalar_t w);
   33.72 +static inline void v4_print(FILE *fp, vec4_t v);
   33.73 +
   33.74 +static inline vec4_t v4_add(vec4_t v1, vec4_t v2);
   33.75 +static inline vec4_t v4_sub(vec4_t v1, vec4_t v2);
   33.76 +static inline vec4_t v4_neg(vec4_t v);
   33.77 +static inline vec4_t v4_mul(vec4_t v1, vec4_t v2);
   33.78 +static inline vec4_t v4_scale(vec4_t v, scalar_t s);
   33.79 +static inline scalar_t v4_dot(vec4_t v1, vec4_t v2);
   33.80 +static inline scalar_t v4_length(vec4_t v);
   33.81 +static inline scalar_t v4_length_sq(vec4_t v);
   33.82 +static inline vec4_t v4_normalize(vec4_t v);
   33.83 +static inline vec4_t v4_transform(vec4_t v, mat4_t m);
   33.84 +
   33.85 +#ifdef __cplusplus
   33.86 +}	/* extern "C" */
   33.87 +
   33.88 +/* when included from C++ source files, also define the vector classes */
   33.89 +#include <iostream>
   33.90 +
   33.91 +/** 2D Vector */
   33.92 +class Vector2 {
   33.93 +public:
   33.94 +	scalar_t x, y;
   33.95 +
   33.96 +	Vector2(scalar_t x = 0.0, scalar_t y = 0.0);
   33.97 +	Vector2(const vec2_t &vec);
   33.98 +	Vector2(const Vector3 &vec);
   33.99 +	Vector2(const Vector4 &vec);
  33.100 +
  33.101 +	inline scalar_t &operator [](int elem);
  33.102 +	inline const scalar_t &operator [](int elem) const;
  33.103 +
  33.104 +	inline scalar_t length() const;
  33.105 +	inline scalar_t length_sq() const;
  33.106 +	void normalize();
  33.107 +	Vector2 normalized() const;
  33.108 +
  33.109 +	void transform(const Matrix3x3 &mat);
  33.110 +	Vector2 transformed(const Matrix3x3 &mat) const;
  33.111 +
  33.112 +	void rotate(scalar_t angle);
  33.113 +	Vector2 rotated(scalar_t angle) const;
  33.114 +
  33.115 +	Vector2 reflection(const Vector2 &normal) const;
  33.116 +	Vector2 refraction(const Vector2 &normal, scalar_t src_ior, scalar_t dst_ior) const;
  33.117 +};
  33.118 +
  33.119 +/* unary operations */
  33.120 +inline Vector2 operator -(const Vector2 &vec);
  33.121 +
  33.122 +/* binary vector (op) vector operations */
  33.123 +inline scalar_t dot_product(const Vector2 &v1, const Vector2 &v2);
  33.124 +
  33.125 +inline Vector2 operator +(const Vector2 &v1, const Vector2 &v2);
  33.126 +inline Vector2 operator -(const Vector2 &v1, const Vector2 &v2);
  33.127 +inline Vector2 operator *(const Vector2 &v1, const Vector2 &v2);
  33.128 +inline Vector2 operator /(const Vector2 &v1, const Vector2 &v2);
  33.129 +inline bool operator ==(const Vector2 &v1, const Vector2 &v2);
  33.130 +
  33.131 +inline void operator +=(Vector2 &v1, const Vector2 &v2);
  33.132 +inline void operator -=(Vector2 &v1, const Vector2 &v2);
  33.133 +inline void operator *=(Vector2 &v1, const Vector2 &v2);
  33.134 +inline void operator /=(Vector2 &v1, const Vector2 &v2);
  33.135 +
  33.136 +/* binary vector (op) scalar and scalar (op) vector operations */
  33.137 +inline Vector2 operator +(const Vector2 &vec, scalar_t scalar);
  33.138 +inline Vector2 operator +(scalar_t scalar, const Vector2 &vec);
  33.139 +inline Vector2 operator -(const Vector2 &vec, scalar_t scalar);
  33.140 +inline Vector2 operator *(const Vector2 &vec, scalar_t scalar);
  33.141 +inline Vector2 operator *(scalar_t scalar, const Vector2 &vec);
  33.142 +inline Vector2 operator /(const Vector2 &vec, scalar_t scalar);
  33.143 +
  33.144 +inline void operator +=(Vector2 &vec, scalar_t scalar);
  33.145 +inline void operator -=(Vector2 &vec, scalar_t scalar);
  33.146 +inline void operator *=(Vector2 &vec, scalar_t scalar);
  33.147 +inline void operator /=(Vector2 &vec, scalar_t scalar);
  33.148 +
  33.149 +std::ostream &operator <<(std::ostream &out, const Vector2 &vec);
  33.150 +
  33.151 +inline Vector2 lerp(const Vector2 &a, const Vector2 &b, scalar_t t);
  33.152 +inline Vector2 catmull_rom_spline(const Vector2 &v0, const Vector2 &v1,
  33.153 +		const Vector2 &v2, const Vector2 &v3, scalar_t t);
  33.154 +
  33.155 +/* 3D Vector */
  33.156 +class Vector3 {
  33.157 +public:
  33.158 +	scalar_t x, y, z;
  33.159 +
  33.160 +	Vector3(scalar_t x = 0.0, scalar_t y = 0.0, scalar_t z = 0.0);
  33.161 +	Vector3(const vec3_t &vec);
  33.162 +	Vector3(const Vector2 &vec);
  33.163 +	Vector3(const Vector4 &vec);
  33.164 +	Vector3(const SphVector &sph);
  33.165 +
  33.166 +	Vector3 &operator =(const SphVector &sph);
  33.167 +
  33.168 +	inline scalar_t &operator [](int elem);
  33.169 +	inline const scalar_t &operator [](int elem) const;
  33.170 +
  33.171 +	inline scalar_t length() const;
  33.172 +	inline scalar_t length_sq() const;
  33.173 +	void normalize();
  33.174 +	Vector3 normalized() const;
  33.175 +
  33.176 +	void transform(const Matrix3x3 &mat);
  33.177 +	Vector3 transformed(const Matrix3x3 &mat) const;
  33.178 +	void transform(const Matrix4x4 &mat);
  33.179 +	Vector3 transformed(const Matrix4x4 &mat) const;
  33.180 +	void transform(const Quaternion &quat);
  33.181 +	Vector3 transformed(const Quaternion &quat) const;
  33.182 +
  33.183 +	void rotate(const Vector3 &euler);
  33.184 +	Vector3 rotated(const Vector3 &euler) const;
  33.185 +
  33.186 +	Vector3 reflection(const Vector3 &normal) const;
  33.187 +	Vector3 refraction(const Vector3 &normal, scalar_t src_ior, scalar_t dst_ior) const;
  33.188 +	Vector3 refraction(const Vector3 &normal, scalar_t ior) const;
  33.189 +};
  33.190 +
  33.191 +/* unary operations */
  33.192 +inline Vector3 operator -(const Vector3 &vec);
  33.193 +
  33.194 +/* binary vector (op) vector operations */
  33.195 +inline scalar_t dot_product(const Vector3 &v1, const Vector3 &v2);
  33.196 +inline Vector3 cross_product(const Vector3 &v1, const Vector3 &v2);
  33.197 +
  33.198 +inline Vector3 operator +(const Vector3 &v1, const Vector3 &v2);
  33.199 +inline Vector3 operator -(const Vector3 &v1, const Vector3 &v2);
  33.200 +inline Vector3 operator *(const Vector3 &v1, const Vector3 &v2);
  33.201 +inline Vector3 operator /(const Vector3 &v1, const Vector3 &v2);
  33.202 +inline bool operator ==(const Vector3 &v1, const Vector3 &v2);
  33.203 +
  33.204 +inline void operator +=(Vector3 &v1, const Vector3 &v2);
  33.205 +inline void operator -=(Vector3 &v1, const Vector3 &v2);
  33.206 +inline void operator *=(Vector3 &v1, const Vector3 &v2);
  33.207 +inline void operator /=(Vector3 &v1, const Vector3 &v2);
  33.208 +
  33.209 +/* binary vector (op) scalar and scalar (op) vector operations */
  33.210 +inline Vector3 operator +(const Vector3 &vec, scalar_t scalar);
  33.211 +inline Vector3 operator +(scalar_t scalar, const Vector3 &vec);
  33.212 +inline Vector3 operator -(const Vector3 &vec, scalar_t scalar);
  33.213 +inline Vector3 operator *(const Vector3 &vec, scalar_t scalar);
  33.214 +inline Vector3 operator *(scalar_t scalar, const Vector3 &vec);
  33.215 +inline Vector3 operator /(const Vector3 &vec, scalar_t scalar);
  33.216 +
  33.217 +inline void operator +=(Vector3 &vec, scalar_t scalar);
  33.218 +inline void operator -=(Vector3 &vec, scalar_t scalar);
  33.219 +inline void operator *=(Vector3 &vec, scalar_t scalar);
  33.220 +inline void operator /=(Vector3 &vec, scalar_t scalar);
  33.221 +
  33.222 +std::ostream &operator <<(std::ostream &out, const Vector3 &vec);
  33.223 +
  33.224 +inline Vector3 lerp(const Vector3 &a, const Vector3 &b, scalar_t t);
  33.225 +inline Vector3 catmull_rom_spline(const Vector3 &v0, const Vector3 &v1,
  33.226 +		const Vector3 &v2, const Vector3 &v3, scalar_t t);
  33.227 +
  33.228 +/* 4D Vector */
  33.229 +class Vector4 {
  33.230 +public:
  33.231 +	scalar_t x, y, z, w;
  33.232 +
  33.233 +	Vector4(scalar_t x = 0.0, scalar_t y = 0.0, scalar_t z = 0.0, scalar_t w = 0.0);
  33.234 +	Vector4(const vec4_t &vec);
  33.235 +	Vector4(const Vector2 &vec);
  33.236 +	Vector4(const Vector3 &vec);
  33.237 +
  33.238 +	inline scalar_t &operator [](int elem);
  33.239 +	inline const scalar_t &operator [](int elem) const;
  33.240 +
  33.241 +	inline scalar_t length() const;
  33.242 +	inline scalar_t length_sq() const;
  33.243 +	void normalize();
  33.244 +	Vector4 normalized() const;
  33.245 +
  33.246 +	void transform(const Matrix4x4 &mat);
  33.247 +	Vector4 transformed(const Matrix4x4 &mat) const;
  33.248 +
  33.249 +	Vector4 reflection(const Vector4 &normal) const;
  33.250 +	Vector4 refraction(const Vector4 &normal, scalar_t src_ior, scalar_t dst_ior) const;
  33.251 +};
  33.252 +
  33.253 +
  33.254 +/* unary operations */
  33.255 +inline Vector4 operator -(const Vector4 &vec);
  33.256 +
  33.257 +/* binary vector (op) vector operations */
  33.258 +inline scalar_t dot_product(const Vector4 &v1, const Vector4 &v2);
  33.259 +inline Vector4 cross_product(const Vector4 &v1, const Vector4 &v2, const Vector4 &v3);
  33.260 +
  33.261 +inline Vector4 operator +(const Vector4 &v1, const Vector4 &v2);
  33.262 +inline Vector4 operator -(const Vector4 &v1, const Vector4 &v2);
  33.263 +inline Vector4 operator *(const Vector4 &v1, const Vector4 &v2);
  33.264 +inline Vector4 operator /(const Vector4 &v1, const Vector4 &v2);
  33.265 +inline bool operator ==(const Vector4 &v1, const Vector4 &v2);
  33.266 +
  33.267 +inline void operator +=(Vector4 &v1, const Vector4 &v2);
  33.268 +inline void operator -=(Vector4 &v1, const Vector4 &v2);
  33.269 +inline void operator *=(Vector4 &v1, const Vector4 &v2);
  33.270 +inline void operator /=(Vector4 &v1, const Vector4 &v2);
  33.271 +
  33.272 +/* binary vector (op) scalar and scalar (op) vector operations */
  33.273 +inline Vector4 operator +(const Vector4 &vec, scalar_t scalar);
  33.274 +inline Vector4 operator +(scalar_t scalar, const Vector4 &vec);
  33.275 +inline Vector4 operator -(const Vector4 &vec, scalar_t scalar);
  33.276 +inline Vector4 operator *(const Vector4 &vec, scalar_t scalar);
  33.277 +inline Vector4 operator *(scalar_t scalar, const Vector4 &vec);
  33.278 +inline Vector4 operator /(const Vector4 &vec, scalar_t scalar);
  33.279 +
  33.280 +inline void operator +=(Vector4 &vec, scalar_t scalar);
  33.281 +inline void operator -=(Vector4 &vec, scalar_t scalar);
  33.282 +inline void operator *=(Vector4 &vec, scalar_t scalar);
  33.283 +inline void operator /=(Vector4 &vec, scalar_t scalar);
  33.284 +
  33.285 +std::ostream &operator <<(std::ostream &out, const Vector4 &vec);
  33.286 +
  33.287 +inline Vector4 lerp(const Vector4 &v0, const Vector4 &v1, scalar_t t);
  33.288 +inline Vector4 catmull_rom_spline(const Vector4 &v0, const Vector4 &v1,
  33.289 +		const Vector4 &v2, const Vector4 &v3, scalar_t t);
  33.290 +
  33.291 +#endif	/* __cplusplus */
  33.292 +
  33.293 +#include "vector.inl"
  33.294 +
  33.295 +#endif	/* VMATH_VECTOR_H_ */
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/libs/vmath/vector.inl	Sun Sep 29 08:20:19 2013 +0300
    34.3 @@ -0,0 +1,761 @@
    34.4 +/*
    34.5 +libvmath - a vector math library
    34.6 +Copyright (C) 2004-2011 John Tsiombikas <nuclear@member.fsf.org>
    34.7 +
    34.8 +This program is free software: you can redistribute it and/or modify
    34.9 +it under the terms of the GNU Lesser General Public License as published
   34.10 +by the Free Software Foundation, either version 3 of the License, or
   34.11 +(at your option) any later version.
   34.12 +
   34.13 +This program is distributed in the hope that it will be useful,
   34.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   34.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   34.16 +GNU Lesser General Public License for more details.
   34.17 +
   34.18 +You should have received a copy of the GNU Lesser General Public License
   34.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
   34.20 +*/
   34.21 +
   34.22 +#include <math.h>
   34.23 +
   34.24 +#ifdef __cplusplus
   34.25 +extern "C" {
   34.26 +#endif	/* __cplusplus */
   34.27 +
   34.28 +/* C 2D vector functions */
   34.29 +static inline vec2_t v2_cons(scalar_t x, scalar_t y)
   34.30 +{
   34.31 +	vec2_t v;
   34.32 +	v.x = x;
   34.33 +	v.y = y;
   34.34 +	return v;
   34.35 +}
   34.36 +
   34.37 +static inline void v2_print(FILE *fp, vec2_t v)
   34.38 +{
   34.39 +	fprintf(fp, "[ %.4f %.4f ]", v.x, v.y);
   34.40 +}
   34.41 +
   34.42 +static inline vec2_t v2_add(vec2_t v1, vec2_t v2)
   34.43 +{
   34.44 +	vec2_t res;
   34.45 +	res.x = v1.x + v2.x;
   34.46 +	res.y = v1.y + v2.y;
   34.47 +	return res;
   34.48 +}
   34.49 +
   34.50 +static inline vec2_t v2_sub(vec2_t v1, vec2_t v2)
   34.51 +{
   34.52 +	vec2_t res;
   34.53 +	res.x = v1.x - v2.x;
   34.54 +	res.y = v1.y - v2.y;
   34.55 +	return res;
   34.56 +}
   34.57 +
   34.58 +static inline vec2_t v2_scale(vec2_t v, scalar_t s)
   34.59 +{
   34.60 +	vec2_t res;
   34.61 +	res.x = v.x * s;
   34.62 +	res.y = v.y * s;
   34.63 +	return res;
   34.64 +}
   34.65 +
   34.66 +static inline scalar_t v2_dot(vec2_t v1, vec2_t v2)
   34.67 +{
   34.68 +	return v1.x * v2.x + v1.y * v2.y;
   34.69 +}
   34.70 +
   34.71 +static inline scalar_t v2_length(vec2_t v)
   34.72 +{
   34.73 +	return sqrt(v.x * v.x + v.y * v.y);
   34.74 +}
   34.75 +
   34.76 +static inline scalar_t v2_length_sq(vec2_t v)
   34.77 +{
   34.78 +	return v.x * v.x + v.y * v.y;
   34.79 +}
   34.80 +
   34.81 +static inline vec2_t v2_normalize(vec2_t v)
   34.82 +{
   34.83 +	scalar_t len = (scalar_t)sqrt(v.x * v.x + v.y * v.y);
   34.84 +	v.x /= len;
   34.85 +	v.y /= len;
   34.86 +	return v;
   34.87 +}
   34.88 +
   34.89 +static inline vec2_t v2_lerp(vec2_t v1, vec2_t v2, scalar_t t)
   34.90 +{
   34.91 +	vec2_t res;
   34.92 +	res.x = v1.x + (v2.x - v1.x) * t;
   34.93 +	res.y = v1.y + (v2.y - v1.y) * t;
   34.94 +	return res;
   34.95 +}
   34.96 +
   34.97 +
   34.98 +/* C 3D vector functions */
   34.99 +static inline vec3_t v3_cons(scalar_t x, scalar_t y, scalar_t z)
  34.100 +{
  34.101 +	vec3_t v;
  34.102 +	v.x = x;
  34.103 +	v.y = y;
  34.104 +	v.z = z;
  34.105 +	return v;
  34.106 +}
  34.107 +
  34.108 +static inline void v3_print(FILE *fp, vec3_t v)
  34.109 +{
  34.110 +	fprintf(fp, "[ %.4f %.4f %.4f ]", v.x, v.y, v.z);
  34.111 +}
  34.112 +
  34.113 +static inline vec3_t v3_add(vec3_t v1, vec3_t v2)
  34.114 +{
  34.115 +	v1.x += v2.x;
  34.116 +	v1.y += v2.y;
  34.117 +	v1.z += v2.z;
  34.118 +	return v1;
  34.119 +}
  34.120 +
  34.121 +static inline vec3_t v3_sub(vec3_t v1, vec3_t v2)
  34.122 +{
  34.123 +	v1.x -= v2.x;
  34.124 +	v1.y -= v2.y;
  34.125 +	v1.z -= v2.z;
  34.126 +	return v1;
  34.127 +}
  34.128 +
  34.129 +static inline vec3_t v3_neg(vec3_t v)
  34.130 +{
  34.131 +	v.x = -v.x;
  34.132 +	v.y = -v.y;
  34.133 +	v.z = -v.z;
  34.134 +	return v;
  34.135 +}
  34.136 +
  34.137 +static inline vec3_t v3_mul(vec3_t v1, vec3_t v2)
  34.138 +{
  34.139 +	v1.x *= v2.x;
  34.140 +	v1.y *= v2.y;
  34.141 +	v1.z *= v2.z;
  34.142 +	return v1;
  34.143 +}
  34.144 +
  34.145 +static inline vec3_t v3_scale(vec3_t v1, scalar_t s)
  34.146 +{
  34.147 +	v1.x *= s;
  34.148 +	v1.y *= s;
  34.149 +	v1.z *= s;
  34.150 +	return v1;
  34.151 +}
  34.152 +
  34.153 +static inline scalar_t v3_dot(vec3_t v1, vec3_t v2)
  34.154 +{
  34.155 +	return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
  34.156 +}
  34.157 +
  34.158 +static inline vec3_t v3_cross(vec3_t v1, vec3_t v2)
  34.159 +{
  34.160 +	vec3_t v;
  34.161 +	v.x = v1.y * v2.z - v1.z * v2.y;
  34.162 +	v.y = v1.z * v2.x - v1.x * v2.z;
  34.163 +	v.z = v1.x * v2.y - v1.y * v2.x;
  34.164 +	return v;
  34.165 +}
  34.166 +
  34.167 +static inline scalar_t v3_length(vec3_t v)
  34.168 +{
  34.169 +	return sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
  34.170 +}
  34.171 +
  34.172 +static inline scalar_t v3_length_sq(vec3_t v)
  34.173 +{
  34.174 +	return v.x * v.x + v.y * v.y + v.z * v.z;
  34.175 +}
  34.176 +
  34.177 +static inline vec3_t v3_normalize(vec3_t v)
  34.178 +{
  34.179 +	scalar_t len = sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
  34.180 +	v.x /= len;
  34.181 +	v.y /= len;
  34.182 +	v.z /= len;
  34.183 +	return v;
  34.184 +}
  34.185 +
  34.186 +static inline vec3_t v3_transform(vec3_t v, mat4_t m)
  34.187 +{
  34.188 +	vec3_t res;
  34.189 +	res.x = m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3];
  34.190 +	res.y = m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3];
  34.191 +	res.z = m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3];
  34.192 +	return res;
  34.193 +}
  34.194 +
  34.195 +static inline vec3_t v3_rotate(vec3_t v, scalar_t x, scalar_t y, scalar_t z)
  34.196 +{
  34.197 +	void m4_rotate(mat4_t, scalar_t, scalar_t, scalar_t);
  34.198 +
  34.199 +	mat4_t m = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
  34.200 +	m4_rotate(m, x, y, z);
  34.201 +	return v3_transform(v, m);
  34.202 +}
  34.203 +
  34.204 +static inline vec3_t v3_rotate_axis(vec3_t v, scalar_t angle, scalar_t x, scalar_t y, scalar_t z)
  34.205 +{
  34.206 +	void m4_rotate_axis(mat4_t, scalar_t, scalar_t, scalar_t, scalar_t);
  34.207 +
  34.208 +	mat4_t m = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
  34.209 +	m4_rotate_axis(m, angle, x, y, z);
  34.210 +	return v3_transform(v, m);
  34.211 +}
  34.212 +
  34.213 +static inline vec3_t v3_rotate_quat(vec3_t v, quat_t q)
  34.214 +{
  34.215 +	quat_t quat_rotate_quat(quat_t, quat_t);
  34.216 +
  34.217 +	quat_t vq = v4_cons(v.x, v.y, v.z, 0.0);
  34.218 +	quat_t res = quat_rotate_quat(vq, q);
  34.219 +	return v3_cons(res.x, res.y, res.z);
  34.220 +}
  34.221 +
  34.222 +static inline vec3_t v3_reflect(vec3_t v, vec3_t n)
  34.223 +{
  34.224 +	scalar_t dot = v3_dot(v, n);
  34.225 +	return v3_sub(v3_scale(n, dot * 2.0), v);
  34.226 +}
  34.227 +
  34.228 +static inline vec3_t v3_lerp(vec3_t v1, vec3_t v2, scalar_t t)
  34.229 +{
  34.230 +	v1.x += (v2.x - v1.x) * t;
  34.231 +	v1.y += (v2.y - v1.y) * t;
  34.232 +	v1.z += (v2.z - v1.z) * t;
  34.233 +	return v1;
  34.234 +}
  34.235 +
  34.236 +/* C 4D vector functions */
  34.237 +static inline vec4_t v4_cons(scalar_t x, scalar_t y, scalar_t z, scalar_t w)
  34.238 +{
  34.239 +	vec4_t v;
  34.240 +	v.x = x;
  34.241 +	v.y = y;
  34.242 +	v.z = z;
  34.243 +	v.w = w;
  34.244 +	return v;
  34.245 +}
  34.246 +
  34.247 +static inline void v4_print(FILE *fp, vec4_t v)
  34.248 +{
  34.249 +	fprintf(fp, "[ %.4f %.4f %.4f %.4f ]", v.x, v.y, v.z, v.w);
  34.250 +}
  34.251 +
  34.252 +static inline vec4_t v4_add(vec4_t v1, vec4_t v2)
  34.253 +{
  34.254 +	v1.x += v2.x;
  34.255 +	v1.y += v2.y;
  34.256 +	v1.z += v2.z;
  34.257 +	v1.w += v2.w;
  34.258 +	return v1;
  34.259 +}
  34.260 +
  34.261 +static inline vec4_t v4_sub(vec4_t v1, vec4_t v2)
  34.262 +{
  34.263 +	v1.x -= v2.x;
  34.264 +	v1.y -= v2.y;
  34.265 +	v1.z -= v2.z;
  34.266 +	v1.w -= v2.w;
  34.267 +	return v1;
  34.268 +}
  34.269 +
  34.270 +static inline vec4_t v4_neg(vec4_t v)
  34.271 +{
  34.272 +	v.x = -v.x;
  34.273 +	v.y = -v.y;
  34.274 +	v.z = -v.z;
  34.275 +	v.w = -v.w;
  34.276 +	return v;
  34.277 +}
  34.278 +
  34.279 +static inline vec4_t v4_mul(vec4_t v1, vec4_t v2)
  34.280 +{
  34.281 +	v1.x *= v2.x;
  34.282 +	v1.y *= v2.y;
  34.283 +	v1.z *= v2.z;
  34.284 +	v1.w *= v2.w;
  34.285 +	return v1;
  34.286 +}
  34.287 +
  34.288 +static inline vec4_t v4_scale(vec4_t v, scalar_t s)
  34.289 +{
  34.290 +	v.x *= s;
  34.291 +	v.y *= s;
  34.292 +	v.z *= s;
  34.293 +	v.w *= s;
  34.294 +	return v;
  34.295 +}
  34.296 +
  34.297 +static inline scalar_t v4_dot(vec4_t v1, vec4_t v2)
  34.298 +{
  34.299 +	return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w;
  34.300 +}
  34.301 +
  34.302 +static inline scalar_t v4_length(vec4_t v)
  34.303 +{
  34.304 +	return sqrt(v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w);
  34.305 +}
  34.306 +
  34.307 +static inline scalar_t v4_length_sq(vec4_t v)
  34.308 +{
  34.309 +	return v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w;
  34.310 +}
  34.311 +
  34.312 +static inline vec4_t v4_normalize(vec4_t v)
  34.313 +{
  34.314 +	scalar_t len = sqrt(v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w);
  34.315 +	v.x /= len;
  34.316 +	v.y /= len;
  34.317 +	v.z /= len;
  34.318 +	v.w /= len;
  34.319 +	return v;
  34.320 +}
  34.321 +
  34.322 +static inline vec4_t v4_transform(vec4_t v, mat4_t m)
  34.323 +{
  34.324 +	vec4_t res;
  34.325 +	res.x = m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w;
  34.326 +	res.y = m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w;
  34.327 +	res.z = m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w;
  34.328 +	res.w = m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3] * v.w;
  34.329 +	return res;
  34.330 +}
  34.331 +
  34.332 +#ifdef __cplusplus
  34.333 +}	/* extern "C" */
  34.334 +
  34.335 +
  34.336 +/* --------------- C++ part -------------- */
  34.337 +
  34.338 +inline scalar_t &Vector2::operator [](int elem) {
  34.339 +	return elem ? y : x;
  34.340 +}
  34.341 +
  34.342 +inline const scalar_t &Vector2::operator [](int elem) const {
  34.343 +	return elem ? y : x;
  34.344 +}
  34.345 +
  34.346 +inline Vector2 operator -(const Vector2 &vec) {
  34.347 +	return Vector2(-vec.x, -vec.y);
  34.348 +}
  34.349 +
  34.350 +inline scalar_t dot_product(const Vector2 &v1, const Vector2 &v2) {
  34.351 +	return v1.x * v2.x + v1.y * v2.y;
  34.352 +}
  34.353 +
  34.354 +inline Vector2 operator +(const Vector2 &v1, const Vector2 &v2) {
  34.355 +	return Vector2(v1.x + v2.x, v1.y + v2.y);
  34.356 +}
  34.357 +
  34.358 +inline Vector2 operator -(const Vector2 &v1, const Vector2 &v2) {
  34.359 +	return Vector2(v1.x - v2.x, v1.y - v2.y);
  34.360 +}
  34.361 +
  34.362 +inline Vector2 operator *(const Vector2 &v1, const Vector2 &v2) {
  34.363 +	return Vector2(v1.x * v2.x, v1.y * v2.y);
  34.364 +}
  34.365 +
  34.366 +inline Vector2 operator /(const Vector2 &v1, const Vector2 &v2) {
  34.367 +	return Vector2(v1.x / v2.x, v1.y / v2.y);
  34.368 +}
  34.369 +
  34.370 +inline bool operator ==(const Vector2 &v1, const Vector2 &v2) {
  34.371 +	return (fabs(v1.x - v2.x) < XSMALL_NUMBER) && (fabs(v1.y - v2.x) < XSMALL_NUMBER);
  34.372 +}
  34.373 +
  34.374 +inline void operator +=(Vector2 &v1, const Vector2 &v2) {
  34.375 +	v1.x += v2.x;
  34.376 +	v1.y += v2.y;
  34.377 +}
  34.378 +
  34.379 +inline void operator -=(Vector2 &v1, const Vector2 &v2) {
  34.380 +	v1.x -= v2.x;
  34.381 +	v1.y -= v2.y;
  34.382 +}
  34.383 +
  34.384 +inline void operator *=(Vector2 &v1, const Vector2 &v2) {
  34.385 +	v1.x *= v2.x;
  34.386 +	v1.y *= v2.y;
  34.387 +}
  34.388 +
  34.389 +inline void operator /=(Vector2 &v1, const Vector2 &v2) {
  34.390 +	v1.x /= v2.x;
  34.391 +	v1.y /= v2.y;
  34.392 +}
  34.393 +
  34.394 +inline Vector2 operator +(const Vector2 &vec, scalar_t scalar) {
  34.395 +	return Vector2(vec.x + scalar, vec.y + scalar);
  34.396 +}
  34.397 +
  34.398 +inline Vector2 operator +(scalar_t scalar, const Vector2 &vec) {
  34.399 +	return Vector2(vec.x + scalar, vec.y + scalar);
  34.400 +}
  34.401 +
  34.402 +inline Vector2 operator -(scalar_t scalar, const Vector2 &vec) {
  34.403 +	return Vector2(vec.x - scalar, vec.y - scalar);
  34.404 +}
  34.405 +
  34.406 +inline Vector2 operator *(const Vector2 &vec, scalar_t scalar) {
  34.407 +	return Vector2(vec.x * scalar, vec.y * scalar);
  34.408 +}
  34.409 +
  34.410 +inline Vector2 operator *(scalar_t scalar, const Vector2 &vec) {
  34.411 +	return Vector2(vec.x * scalar, vec.y * scalar);
  34.412 +}
  34.413 +
  34.414 +inline Vector2 operator /(const Vector2 &vec, scalar_t scalar) {
  34.415 +	return Vector2(vec.x / scalar, vec.y / scalar);
  34.416 +}
  34.417 +
  34.418 +inline void operator +=(Vector2 &vec, scalar_t scalar) {
  34.419 +	vec.x += scalar;
  34.420 +	vec.y += scalar;
  34.421 +}
  34.422 +
  34.423 +inline void operator -=(Vector2 &vec, scalar_t scalar) {
  34.424 +	vec.x -= scalar;
  34.425 +	vec.y -= scalar;
  34.426 +}
  34.427 +
  34.428 +inline void operator *=(Vector2 &vec, scalar_t scalar) {
  34.429 +	vec.x *= scalar;
  34.430 +	vec.y *= scalar;
  34.431 +}
  34.432 +
  34.433 +inline void operator /=(Vector2 &vec, scalar_t scalar) {
  34.434 +	vec.x /= scalar;
  34.435 +	vec.y /= scalar;
  34.436 +}
  34.437 +
  34.438 +inline scalar_t Vector2::length() const {
  34.439 +	return sqrt(x*x + y*y);
  34.440 +}
  34.441 +
  34.442 +inline scalar_t Vector2::length_sq() const {
  34.443 +	return x*x + y*y;
  34.444 +}
  34.445 +
  34.446 +inline Vector2 lerp(const Vector2 &a, const Vector2 &b, scalar_t t)
  34.447 +{
  34.448 +	return a + (b - a) * t;
  34.449 +}
  34.450 +
  34.451 +inline Vector2 catmull_rom_spline(const Vector2 &v0, const Vector2 &v1,
  34.452 +		const Vector2 &v2, const Vector2 &v3, scalar_t t)
  34.453 +{
  34.454 +	scalar_t spline(scalar_t, scalar_t, scalar_t, scalar_t, scalar_t);
  34.455 +	scalar_t x = spline(v0.x, v1.x, v2.x, v3.x, t);
  34.456 +	scalar_t y = spline(v0.y, v1.y, v2.y, v3.y, t);
  34.457 +	return Vector2(x, y);
  34.458 +}
  34.459 +
  34.460 +
  34.461 +/* ------------- Vector3 -------------- */
  34.462 +
  34.463 +inline scalar_t &Vector3::operator [](int elem) {
  34.464 +	return elem ? (elem == 1 ? y : z) : x;
  34.465 +}
  34.466 +
  34.467 +inline const scalar_t &Vector3::operator [](int elem) const {
  34.468 +	return elem ? (elem == 1 ? y : z) : x;
  34.469 +}
  34.470 +
  34.471 +/* unary operations */
  34.472 +inline Vector3 operator -(const Vector3 &vec) {
  34.473 +	return Vector3(-vec.x, -vec.y, -vec.z);
  34.474 +}
  34.475 +
  34.476 +/* binary vector (op) vector operations */
  34.477 +inline scalar_t dot_product(const Vector3 &v1, const Vector3 &v2) {
  34.478 +	return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
  34.479 +}
  34.480 +
  34.481 +inline Vector3 cross_product(const Vector3 &v1, const Vector3 &v2) {
  34.482 +	return Vector3(v1.y * v2.z - v1.z * v2.y,  v1.z * v2.x - v1.x * v2.z,  v1.x * v2.y - v1.y * v2.x);
  34.483 +}
  34.484 +
  34.485 +
  34.486 +inline Vector3 operator +(const Vector3 &v1, const Vector3 &v2) {
  34.487 +	return Vector3(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
  34.488 +}
  34.489 +
  34.490 +inline Vector3 operator -(const Vector3 &v1, const Vector3 &v2) {
  34.491 +	return Vector3(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
  34.492 +}
  34.493 +
  34.494 +inline Vector3 operator *(const Vector3 &v1, const Vector3 &v2) {
  34.495 +	return Vector3(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z);
  34.496 +}
  34.497 +
  34.498 +inline Vector3 operator /(const Vector3 &v1, const Vector3 &v2) {
  34.499 +	return Vector3(v1.x / v2.x, v1.y / v2.y, v1.z / v2.z);
  34.500 +}
  34.501 +
  34.502 +inline bool operator ==(const Vector3 &v1, const Vector3 &v2) {
  34.503 +	return (fabs(v1.x - v2.x) < XSMALL_NUMBER) && (fabs(v1.y - v2.y) < XSMALL_NUMBER) && (fabs(v1.z - v2.z) < XSMALL_NUMBER);
  34.504 +}
  34.505 +
  34.506 +inline void operator +=(Vector3 &v1, const Vector3 &v2) {
  34.507 +	v1.x += v2.x;
  34.508 +	v1.y += v2.y;
  34.509 +	v1.z += v2.z;
  34.510 +}
  34.511 +
  34.512 +inline void operator -=(Vector3 &v1, const Vector3 &v2) {
  34.513 +	v1.x -= v2.x;
  34.514 +	v1.y -= v2.y;
  34.515 +	v1.z -= v2.z;
  34.516 +}
  34.517 +
  34.518 +inline void operator *=(Vector3 &v1, const Vector3 &v2) {
  34.519 +	v1.x *= v2.x;
  34.520 +	v1.y *= v2.y;
  34.521 +	v1.z *= v2.z;
  34.522 +}
  34.523 +
  34.524 +inline void operator /=(Vector3 &v1, const Vector3 &v2) {
  34.525 +	v1.x /= v2.x;
  34.526 +	v1.y /= v2.y;
  34.527 +	v1.z /= v2.z;
  34.528 +}
  34.529 +/* binary vector (op) scalar and scalar (op) vector operations */
  34.530 +inline Vector3 operator +(const Vector3 &vec, scalar_t scalar) {
  34.531 +	return Vector3(vec.x + scalar, vec.y + scalar, vec.z + scalar);
  34.532 +}
  34.533 +
  34.534 +inline Vector3 operator +(scalar_t scalar, const Vector3 &vec) {
  34.535 +	return Vector3(vec.x + scalar, vec.y + scalar, vec.z + scalar);
  34.536 +}
  34.537 +
  34.538 +inline Vector3 operator -(const Vector3 &vec, scalar_t scalar) {
  34.539 +	return Vector3(vec.x - scalar, vec.y - scalar, vec.z - scalar);
  34.540 +}
  34.541 +
  34.542 +inline Vector3 operator *(const Vector3 &vec, scalar_t scalar) {
  34.543 +	return Vector3(vec.x * scalar, vec.y * scalar, vec.z * scalar);
  34.544 +}
  34.545 +
  34.546 +inline Vector3 operator *(scalar_t scalar, const Vector3 &vec) {
  34.547 +	return Vector3(vec.x * scalar, vec.y * scalar, vec.z * scalar);
  34.548 +}
  34.549 +
  34.550 +inline Vector3 operator /(const Vector3 &vec, scalar_t scalar) {
  34.551 +	return Vector3(vec.x / scalar, vec.y / scalar, vec.z / scalar);
  34.552 +}
  34.553 +
  34.554 +inline void operator +=(Vector3 &vec, scalar_t scalar) {
  34.555 +	vec.x += scalar;
  34.556 +	vec.y += scalar;
  34.557 +	vec.z += scalar;
  34.558 +}
  34.559 +
  34.560 +inline void operator -=(Vector3 &vec, scalar_t scalar) {
  34.561 +	vec.x -= scalar;
  34.562 +	vec.y -= scalar;
  34.563 +	vec.z -= scalar;
  34.564 +}
  34.565 +
  34.566 +inline void operator *=(Vector3 &vec, scalar_t scalar) {
  34.567 +	vec.x *= scalar;
  34.568 +	vec.y *= scalar;
  34.569 +	vec.z *= scalar;
  34.570 +}
  34.571 +
  34.572 +inline void operator /=(Vector3 &vec, scalar_t scalar) {
  34.573 +	vec.x /= scalar;
  34.574 +	vec.y /= scalar;
  34.575 +	vec.z /= scalar;
  34.576 +}
  34.577 +
  34.578 +inline scalar_t Vector3::length() const {
  34.579 +	return sqrt(x*x + y*y + z*z);
  34.580 +}
  34.581 +inline scalar_t Vector3::length_sq() const {
  34.582 +	return x*x + y*y + z*z;
  34.583 +}
  34.584 +
  34.585 +inline Vector3 lerp(const Vector3 &a, const Vector3 &b, scalar_t t) {
  34.586 +	return a + (b - a) * t;
  34.587 +}
  34.588 +
  34.589 +inline Vector3 catmull_rom_spline(const Vector3 &v0, const Vector3 &v1,
  34.590 +		const Vector3 &v2, const Vector3 &v3, scalar_t t)
  34.591 +{
  34.592 +	scalar_t spline(scalar_t, scalar_t, scalar_t, scalar_t, scalar_t);
  34.593 +	scalar_t x = spline(v0.x, v1.x, v2.x, v3.x, t);
  34.594 +	scalar_t y = spline(v0.y, v1.y, v2.y, v3.y, t);
  34.595 +	scalar_t z = spline(v0.z, v1.z, v2.z, v3.z, t);
  34.596 +	return Vector3(x, y, z);
  34.597 +}
  34.598 +
  34.599 +/* ----------- Vector4 ----------------- */
  34.600 +
  34.601 +inline scalar_t &Vector4::operator [](int elem) {
  34.602 +	return elem ? (elem == 1 ? y : (elem == 2 ? z : w)) : x;
  34.603 +}
  34.604 +
  34.605 +inline const scalar_t &Vector4::operator [](int elem) const {
  34.606 +	return elem ? (elem == 1 ? y : (elem == 2 ? z : w)) : x;
  34.607 +}
  34.608 +
  34.609 +inline Vector4 operator -(const Vector4 &vec) {
  34.610 +	return Vector4(-vec.x, -vec.y, -vec.z, -vec.w);
  34.611 +}
  34.612 +
  34.613 +inline scalar_t dot_product(const Vector4 &v1, const Vector4 &v2) {
  34.614 +	return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w;
  34.615 +}
  34.616 +
  34.617 +inline Vector4 cross_product(const Vector4 &v1, const Vector4 &v2, const Vector4 &v3) {
  34.618 +	scalar_t a, b, c, d, e, f;       /* Intermediate Values */
  34.619 +    Vector4 result;
  34.620 +
  34.621 +    /* Calculate intermediate values. */
  34.622 +    a = (v2.x * v3.y) - (v2.y * v3.x);
  34.623 +    b = (v2.x * v3.z) - (v2.z * v3.x);
  34.624 +    c = (v2.x * v3.w) - (v2.w * v3.x);
  34.625 +    d = (v2.y * v3.z) - (v2.z * v3.y);
  34.626 +    e = (v2.y * v3.w) - (v2.w * v3.y);
  34.627 +    f = (v2.z * v3.w) - (v2.w * v3.z);
  34.628 +
  34.629 +    /* Calculate the result-vector components. */
  34.630 +    result.x =   (v1.y * f) - (v1.z * e) + (v1.w * d);
  34.631 +    result.y = - (v1.x * f) + (v1.z * c) - (v1.w * b);
  34.632 +    result.z =   (v1.x * e) - (v1.y * c) + (v1.w * a);
  34.633 +    result.w = - (v1.x * d) + (v1.y * b) - (v1.z * a);
  34.634 +    return result;
  34.635 +}
  34.636 +
  34.637 +inline Vector4 operator +(const Vector4 &v1, const Vector4 &v2) {
  34.638 +	return Vector4(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z, v1.w + v2.w);
  34.639 +}
  34.640 +
  34.641 +inline Vector4 operator -(const Vector4 &v1, const Vector4 &v2) {
  34.642 +	return Vector4(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z, v1.w - v2.w);
  34.643 +}
  34.644 +
  34.645 +inline Vector4 operator *(const Vector4 &v1, const Vector4 &v2) {
  34.646 +	return Vector4(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z, v1.w * v2.w);
  34.647 +}
  34.648 +
  34.649 +inline Vector4 operator /(const Vector4 &v1, const Vector4 &v2) {
  34.650 +	return Vector4(v1.x / v2.x, v1.y / v2.y, v1.z / v2.z, v1.w / v2.w);
  34.651 +}
  34.652 +
  34.653 +inline bool operator ==(const Vector4 &v1, const Vector4 &v2) {
  34.654 +	return	(fabs(v1.x - v2.x) < XSMALL_NUMBER) &&
  34.655 +			(fabs(v1.y - v2.y) < XSMALL_NUMBER) &&
  34.656 +			(fabs(v1.z - v2.z) < XSMALL_NUMBER) &&
  34.657 +			(fabs(v1.w - v2.w) < XSMALL_NUMBER);
  34.658 +}
  34.659 +
  34.660 +inline void operator +=(Vector4 &v1, const Vector4 &v2) {
  34.661 +	v1.x += v2.x;
  34.662 +	v1.y += v2.y;
  34.663 +	v1.z += v2.z;
  34.664 +	v1.w += v2.w;
  34.665 +}
  34.666 +
  34.667 +inline void operator -=(Vector4 &v1, const Vector4 &v2) {
  34.668 +	v1.x -= v2.x;
  34.669 +	v1.y -= v2.y;
  34.670 +	v1.z -= v2.z;
  34.671 +	v1.w -= v2.w;
  34.672 +}
  34.673 +
  34.674 +inline void operator *=(Vector4 &v1, const Vector4 &v2) {
  34.675 +	v1.x *= v2.x;
  34.676 +	v1.y *= v2.y;
  34.677 +	v1.z *= v2.z;
  34.678 +	v1.w *= v2.w;
  34.679 +}
  34.680 +
  34.681 +inline void operator /=(Vector4 &v1, const Vector4 &v2) {
  34.682 +	v1.x /= v2.x;
  34.683 +	v1.y /= v2.y;
  34.684 +	v1.z /= v2.z;
  34.685 +	v1.w /= v2.w;
  34.686 +}
  34.687 +
  34.688 +/* binary vector (op) scalar and scalar (op) vector operations */
  34.689 +inline Vector4 operator +(const Vector4 &vec, scalar_t scalar) {
  34.690 +	return Vector4(vec.x + scalar, vec.y + scalar, vec.z + scalar, vec.w + scalar);
  34.691 +}
  34.692 +
  34.693 +inline Vector4 operator +(scalar_t scalar, const Vector4 &vec) {
  34.694 +	return Vector4(vec.x + scalar, vec.y + scalar, vec.z + scalar, vec.w + scalar);
  34.695 +}
  34.696 +
  34.697 +inline Vector4 operator -(const Vector4 &vec, scalar_t scalar) {
  34.698 +	return Vector4(vec.x - scalar, vec.y - scalar, vec.z - scalar, vec.w - scalar);
  34.699 +}
  34.700 +
  34.701 +inline Vector4 operator *(const Vector4 &vec, scalar_t scalar) {
  34.702 +	return Vector4(vec.x * scalar, vec.y * scalar, vec.z * scalar, vec.w * scalar);
  34.703 +}
  34.704 +
  34.705 +inline Vector4 operator *(scalar_t scalar, const Vector4 &vec) {
  34.706 +	return Vector4(vec.x * scalar, vec.y * scalar, vec.z * scalar, vec.w * scalar);
  34.707 +}
  34.708 +
  34.709 +inline Vector4 operator /(const Vector4 &vec, scalar_t scalar) {
  34.710 +	return Vector4(vec.x / scalar, vec.y / scalar, vec.z / scalar, vec.w / scalar);
  34.711 +}
  34.712 +
  34.713 +inline void operator +=(Vector4 &vec, scalar_t scalar) {
  34.714 +	vec.x += scalar;
  34.715 +	vec.y += scalar;
  34.716 +	vec.z += scalar;
  34.717 +	vec.w += scalar;
  34.718 +}
  34.719 +
  34.720 +inline void operator -=(Vector4 &vec, scalar_t scalar) {
  34.721 +	vec.x -= scalar;
  34.722 +	vec.y -= scalar;
  34.723 +	vec.z -= scalar;
  34.724 +	vec.w -= scalar;
  34.725 +}
  34.726 +
  34.727 +inline void operator *=(Vector4 &vec, scalar_t scalar) {
  34.728 +	vec.x *= scalar;
  34.729 +	vec.y *= scalar;
  34.730 +	vec.z *= scalar;
  34.731 +	vec.w *= scalar;
  34.732 +}
  34.733 +
  34.734 +inline void operator /=(Vector4 &vec, scalar_t scalar) {
  34.735 +	vec.x /= scalar;
  34.736 +	vec.y /= scalar;
  34.737 +	vec.z /= scalar;
  34.738 +	vec.w /= scalar;
  34.739 +}
  34.740 +
  34.741 +inline scalar_t Vector4::length() const {
  34.742 +	return sqrt(x*x + y*y + z*z + w*w);
  34.743 +}
  34.744 +inline scalar_t Vector4::length_sq() const {
  34.745 +	return x*x + y*y + z*z + w*w;
  34.746 +}
  34.747 +
  34.748 +inline Vector4 lerp(const Vector4 &v0, const Vector4 &v1, scalar_t t)
  34.749 +{
  34.750 +	return v0 + (v1 - v0) * t;
  34.751 +}
  34.752 +
  34.753 +inline Vector4 catmull_rom_spline(const Vector4 &v0, const Vector4 &v1,
  34.754 +		const Vector4 &v2, const Vector4 &v3, scalar_t t)
  34.755 +{
  34.756 +	scalar_t spline(scalar_t, scalar_t, scalar_t, scalar_t, scalar_t);
  34.757 +	scalar_t x = spline(v0.x, v1.x, v2.x, v3.x, t);
  34.758 +	scalar_t y = spline(v0.y, v1.y, v2.y, v3.y, t);
  34.759 +	scalar_t z = spline(v0.z, v1.z, v2.z, v3.z, t);
  34.760 +	scalar_t w = spline(v0.w, v1.w, v2.w, v3.w, t);
  34.761 +	return Vector4(x, y, z, w);
  34.762 +}
  34.763 +
  34.764 +#endif	/* __cplusplus */
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/libs/vmath/vmath.c	Sun Sep 29 08:20:19 2013 +0300
    35.3 @@ -0,0 +1,336 @@
    35.4 +/*
    35.5 +libvmath - a vector math library
    35.6 +Copyright (C) 2004-2011 John Tsiombikas <nuclear@member.fsf.org>
    35.7 +
    35.8 +This program is free software: you can redistribute it and/or modify
    35.9 +it under the terms of the GNU Lesser General Public License as published
   35.10 +by the Free Software Foundation, either version 3 of the License, or
   35.11 +(at your option) any later version.
   35.12 +
   35.13 +This program is distributed in the hope that it will be useful,
   35.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   35.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   35.16 +GNU Lesser General Public License for more details.
   35.17 +
   35.18 +You should have received a copy of the GNU Lesser General Public License
   35.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
   35.20 +*/
   35.21 +
   35.22 +#include <stdlib.h>
   35.23 +#include <math.h>
   35.24 +#include "vmath.h"
   35.25 +
   35.26 +/** Numerical calculation of integrals using simpson's rule */
   35.27 +scalar_t integral(scalar_t (*f)(scalar_t), scalar_t low, scalar_t high, int samples)
   35.28 +{
   35.29 +	int i;
   35.30 +	scalar_t h = (high - low) / (scalar_t)samples;
   35.31 +	scalar_t sum = 0.0;
   35.32 +
   35.33 +	for(i=0; i<samples+1; i++) {
   35.34 +		scalar_t y = f((scalar_t)i * h + low);
   35.35 +		sum += ((!i || i == samples) ? y : ((i % 2) ? 4.0 * y : 2.0 * y)) * (h / 3.0);
   35.36 +	}
   35.37 +	return sum;
   35.38 +}
   35.39 +
   35.40 +/** Gaussuan function */
   35.41 +scalar_t gaussian(scalar_t x, scalar_t mean, scalar_t sdev)
   35.42 +{
   35.43 +	scalar_t exponent = -SQ(x - mean) / (2.0 * SQ(sdev));
   35.44 +	return 1.0 - -pow(M_E, exponent) / (sdev * sqrt(TWO_PI));
   35.45 +}
   35.46 +
   35.47 +
   35.48 +/** b-spline approximation */
   35.49 +scalar_t bspline(scalar_t a, scalar_t b, scalar_t c, scalar_t d, scalar_t t)
   35.50 +{
   35.51 +	vec4_t tmp;
   35.52 +	scalar_t tsq = t * t;
   35.53 +
   35.54 +	static mat4_t bspline_mat = {
   35.55 +		{-1,  3, -3,  1},
   35.56 +		{3, -6,  3,  0},
   35.57 +		{-3,  0,  3,  0},
   35.58 +		{1,  4,  1,  0}
   35.59 +	};
   35.60 +
   35.61 +	tmp = v4_scale(v4_transform(v4_cons(a, b, c, d), bspline_mat), 1.0 / 6.0);
   35.62 +	return v4_dot(v4_cons(tsq * t, tsq, t, 1.0), tmp);
   35.63 +}
   35.64 +
   35.65 +/** Catmull-rom spline interpolation */
   35.66 +scalar_t spline(scalar_t a, scalar_t b, scalar_t c, scalar_t d, scalar_t t)
   35.67 +{
   35.68 +	vec4_t tmp;
   35.69 +	scalar_t tsq = t * t;
   35.70 +
   35.71 +	static mat4_t crspline_mat = {
   35.72 +		{-1,  3, -3,  1},
   35.73 +		{2, -5,  4, -1},
   35.74 +		{-1,  0,  1,  0},
   35.75 +		{0,  2,  0,  0}
   35.76 +	};
   35.77 +
   35.78 +	tmp = v4_scale(v4_transform(v4_cons(a, b, c, d), crspline_mat), 0.5);
   35.79 +	return v4_dot(v4_cons(tsq * t, tsq, t, 1.0), tmp);
   35.80 +}
   35.81 +
   35.82 +/** Bezier interpolation */
   35.83 +scalar_t bezier(scalar_t a, scalar_t b, scalar_t c, scalar_t d, scalar_t t)
   35.84 +{
   35.85 +	scalar_t omt, omt3, t3, f;
   35.86 +	t3 = t * t * t;
   35.87 +	omt = 1.0f - t;
   35.88 +	omt3 = omt * omt * omt;
   35.89 +	f = 3 * t * omt;
   35.90 +
   35.91 +	return (a * omt3) + (b * f * omt) + (c * f * t) + (d * t3);
   35.92 +}
   35.93 +
   35.94 +/* ---- Ken Perlin's implementation of noise ---- */
   35.95 +
   35.96 +#define B	0x100
   35.97 +#define BM	0xff
   35.98 +#define N	0x1000
   35.99 +#define NP	12   /* 2^N */
  35.100 +#define NM	0xfff
  35.101 +
  35.102 +#define s_curve(t) (t * t * (3.0f - 2.0f * t))
  35.103 +
  35.104 +#define setup(elem, b0, b1, r0, r1) \
  35.105 +	do {							\
  35.106 +		scalar_t t = elem + N;		\
  35.107 +		b0 = ((int)t) & BM;			\
  35.108 +		b1 = (b0 + 1) & BM;			\
  35.109 +		r0 = t - (int)t;			\
  35.110 +		r1 = r0 - 1.0f;				\
  35.111 +	} while(0)
  35.112 +
  35.113 +
  35.114 +static int perm[B + B + 2];			/* permuted index from g_n onto themselves */
  35.115 +static vec3_t grad3[B + B + 2];		/* 3D random gradients */
  35.116 +static vec2_t grad2[B + B + 2];		/* 2D random gradients */
  35.117 +static scalar_t grad1[B + B + 2];	/* 1D random ... slopes */
  35.118 +static int tables_valid;
  35.119 +
  35.120 +static void init_noise()
  35.121 +{
  35.122 +	int i;
  35.123 +
  35.124 +	/* calculate random gradients */
  35.125 +	for(i=0; i<B; i++) {
  35.126 +		perm[i] = i;	/* .. and initialize permutation mapping to identity */
  35.127 +
  35.128 +		grad1[i] = (scalar_t)((rand() % (B + B)) - B) / B;
  35.129 +
  35.130 +		grad2[i].x = (scalar_t)((rand() % (B + B)) - B) / B;
  35.131 +		grad2[i].y = (scalar_t)((rand() % (B + B)) - B) / B;
  35.132 +		grad2[i] = v2_normalize(grad2[i]);
  35.133 +
  35.134 +		grad3[i].x = (scalar_t)((rand() % (B + B)) - B) / B;
  35.135 +		grad3[i].y = (scalar_t)((rand() % (B + B)) - B) / B;
  35.136 +		grad3[i].z = (scalar_t)((rand() % (B + B)) - B) / B;
  35.137 +		grad3[i] = v3_normalize(grad3[i]);
  35.138 +	}
  35.139 +
  35.140 +	/* permute indices by swapping them randomly */
  35.141 +	for(i=0; i<B; i++) {
  35.142 +		int rand_idx = rand() % B;
  35.143 +
  35.144 +		int tmp = perm[i];
  35.145 +		perm[i] = perm[rand_idx];
  35.146 +		perm[rand_idx] = tmp;
  35.147 +	}
  35.148 +
  35.149 +	/* fill up the rest of the arrays by duplicating the existing gradients */
  35.150 +	/* and permutations */
  35.151 +	for(i=0; i<B+2; i++) {
  35.152 +		perm[B + i] = perm[i];
  35.153 +		grad1[B + i] = grad1[i];
  35.154 +		grad2[B + i] = grad2[i];
  35.155 +		grad3[B + i] = grad3[i];
  35.156 +	}
  35.157 +}
  35.158 +
  35.159 +scalar_t noise1(scalar_t x)
  35.160 +{
  35.161 +	int bx0, bx1;
  35.162 +	scalar_t rx0, rx1, sx, u, v;
  35.163 +
  35.164 +	if(!tables_valid) {
  35.165 +		init_noise();
  35.166 +		tables_valid = 1;
  35.167 +	}
  35.168 +
  35.169 +	setup(x, bx0, bx1, rx0, rx1);
  35.170 +	sx = s_curve(rx0);
  35.171 +	u = rx0 * grad1[perm[bx0]];
  35.172 +	v = rx1 * grad1[perm[bx1]];
  35.173 +
  35.174 +	return lerp(u, v, sx);
  35.175 +}
  35.176 +
  35.177 +scalar_t noise2(scalar_t x, scalar_t y)
  35.178 +{
  35.179 +	int i, j, b00, b10, b01, b11;
  35.180 +	int bx0, bx1, by0, by1;
  35.181 +	scalar_t rx0, rx1, ry0, ry1;
  35.182 +	scalar_t sx, sy, u, v, a, b;
  35.183 +
  35.184 +	if(!tables_valid) {
  35.185 +		init_noise();
  35.186 +		tables_valid = 1;
  35.187 +	}
  35.188 +
  35.189 +	setup(x, bx0, bx1, rx0, rx1);
  35.190 +	setup(y, by0, by1, ry0, ry1);
  35.191 +
  35.192 +	i = perm[bx0];
  35.193 +	j = perm[bx1];
  35.194 +
  35.195 +	b00 = perm[i + by0];
  35.196 +	b10 = perm[j + by0];
  35.197 +	b01 = perm[i + by1];
  35.198 +	b11 = perm[j + by1];
  35.199 +
  35.200 +	/* calculate hermite inteprolating factors */
  35.201 +	sx = s_curve(rx0);
  35.202 +	sy = s_curve(ry0);
  35.203 +
  35.204 +	/* interpolate along the left edge */
  35.205 +	u = v2_dot(grad2[b00], v2_cons(rx0, ry0));
  35.206 +	v = v2_dot(grad2[b10], v2_cons(rx1, ry0));
  35.207 +	a = lerp(u, v, sx);
  35.208 +
  35.209 +	/* interpolate along the right edge */
  35.210 +	u = v2_dot(grad2[b01], v2_cons(rx0, ry1));
  35.211 +	v = v2_dot(grad2[b11], v2_cons(rx1, ry1));
  35.212 +	b = lerp(u, v, sx);
  35.213 +
  35.214 +	/* interpolate between them */
  35.215 +	return lerp(a, b, sy);
  35.216 +}
  35.217 +
  35.218 +scalar_t noise3(scalar_t x, scalar_t y, scalar_t z)
  35.219 +{
  35.220 +	int i, j;
  35.221 +	int bx0, bx1, by0, by1, bz0, bz1;
  35.222 +	int b00, b10, b01, b11;
  35.223 +	scalar_t rx0, rx1, ry0, ry1, rz0, rz1;
  35.224 +	scalar_t sx, sy, sz;
  35.225 +	scalar_t u, v, a, b, c, d;
  35.226 +
  35.227 +	if(!tables_valid) {
  35.228 +		init_noise();
  35.229 +		tables_valid = 1;
  35.230 +	}
  35.231 +
  35.232 +	setup(x, bx0, bx1, rx0, rx1);
  35.233 +	setup(y, by0, by1, ry0, ry1);
  35.234 +	setup(z, bz0, bz1, rz0, rz1);
  35.235 +
  35.236 +	i = perm[bx0];
  35.237 +	j = perm[bx1];
  35.238 +
  35.239 +	b00 = perm[i + by0];
  35.240 +	b10 = perm[j + by0];
  35.241 +	b01 = perm[i + by1];
  35.242 +	b11 = perm[j + by1];
  35.243 +
  35.244 +	/* calculate hermite interpolating factors */
  35.245 +	sx = s_curve(rx0);
  35.246 +	sy = s_curve(ry0);
  35.247 +	sz = s_curve(rz0);
  35.248 +
  35.249 +	/* interpolate along the top slice of the cell */
  35.250 +	u = v3_dot(grad3[b00 + bz0], v3_cons(rx0, ry0, rz0));
  35.251 +	v = v3_dot(grad3[b10 + bz0], v3_cons(rx1, ry0, rz0));
  35.252 +	a = lerp(u, v, sx);
  35.253 +
  35.254 +	u = v3_dot(grad3[b01 + bz0], v3_cons(rx0, ry1, rz0));
  35.255 +	v = v3_dot(grad3[b11 + bz0], v3_cons(rx1, ry1, rz0));
  35.256 +	b = lerp(u, v, sx);
  35.257 +
  35.258 +	c = lerp(a, b, sy);
  35.259 +
  35.260 +	/* interpolate along the bottom slice of the cell */
  35.261 +	u = v3_dot(grad3[b00 + bz0], v3_cons(rx0, ry0, rz1));
  35.262 +	v = v3_dot(grad3[b10 + bz0], v3_cons(rx1, ry0, rz1));
  35.263 +	a = lerp(u, v, sx);
  35.264 +
  35.265 +	u = v3_dot(grad3[b01 + bz0], v3_cons(rx0, ry1, rz1));
  35.266 +	v = v3_dot(grad3[b11 + bz0], v3_cons(rx1, ry1, rz1));
  35.267 +	b = lerp(u, v, sx);
  35.268 +
  35.269 +	d = lerp(a, b, sy);
  35.270 +
  35.271 +	/* interpolate between slices */
  35.272 +	return lerp(c, d, sz);
  35.273 +}
  35.274 +
  35.275 +scalar_t fbm1(scalar_t x, int octaves)
  35.276 +{
  35.277 +	int i;
  35.278 +	scalar_t res = 0.0f, freq = 1.0f;
  35.279 +	for(i=0; i<octaves; i++) {
  35.280 +		res += noise1(x * freq) / freq;
  35.281 +		freq *= 2.0f;
  35.282 +	}
  35.283 +	return res;
  35.284 +}
  35.285 +
  35.286 +scalar_t fbm2(scalar_t x, scalar_t y, int octaves)
  35.287 +{
  35.288 +	int i;
  35.289 +	scalar_t res = 0.0f, freq = 1.0f;
  35.290 +	for(i=0; i<octaves; i++) {
  35.291 +		res += noise2(x * freq, y * freq) / freq;
  35.292 +		freq *= 2.0f;
  35.293 +	}
  35.294 +	return res;
  35.295 +}
  35.296 +
  35.297 +scalar_t fbm3(scalar_t x, scalar_t y, scalar_t z, int octaves)
  35.298 +{
  35.299 +	int i;
  35.300 +	scalar_t res = 0.0f, freq = 1.0f;
  35.301 +	for(i=0; i<octaves; i++) {
  35.302 +		res += noise3(x * freq, y * freq, z * freq) / freq;
  35.303 +		freq *= 2.0f;
  35.304 +	}
  35.305 +	return res;
  35.306 +}
  35.307 +
  35.308 +scalar_t turbulence1(scalar_t x, int octaves)
  35.309 +{
  35.310 +	int i;
  35.311 +	scalar_t res = 0.0f, freq = 1.0f;
  35.312 +	for(i=0; i<octaves; i++) {
  35.313 +		res += fabs(noise1(x * freq) / freq);
  35.314 +		freq *= 2.0f;
  35.315 +	}
  35.316 +	return res;
  35.317 +}
  35.318 +
  35.319 +scalar_t turbulence2(scalar_t x, scalar_t y, int octaves)
  35.320 +{
  35.321 +	int i;
  35.322 +	scalar_t res = 0.0f, freq = 1.0f;
  35.323 +	for(i=0; i<octaves; i++) {
  35.324 +		res += fabs(noise2(x * freq, y * freq) / freq);
  35.325 +		freq *= 2.0f;
  35.326 +	}
  35.327 +	return res;
  35.328 +}
  35.329 +
  35.330 +scalar_t turbulence3(scalar_t x, scalar_t y, scalar_t z, int octaves)
  35.331 +{
  35.332 +	int i;
  35.333 +	scalar_t res = 0.0f, freq = 1.0f;
  35.334 +	for(i=0; i<octaves; i++) {
  35.335 +		res += fabs(noise3(x * freq, y * freq, z * freq) / freq);
  35.336 +		freq *= 2.0f;
  35.337 +	}
  35.338 +	return res;
  35.339 +}
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/libs/vmath/vmath.h	Sun Sep 29 08:20:19 2013 +0300
    36.3 @@ -0,0 +1,94 @@
    36.4 +/*
    36.5 +libvmath - a vector math library
    36.6 +Copyright (C) 2004-2013 John Tsiombikas <nuclear@member.fsf.org>
    36.7 +
    36.8 +This program is free software: you can redistribute it and/or modify
    36.9 +it under the terms of the GNU Lesser General Public License as published
   36.10 +by the Free Software Foundation, either version 3 of the License, or
   36.11 +(at your option) any later version.
   36.12 +
   36.13 +This program is distributed in the hope that it will be useful,
   36.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   36.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   36.16 +GNU Lesser General Public License for more details.
   36.17 +
   36.18 +You should have received a copy of the GNU Lesser General Public License
   36.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
   36.20 +*/
   36.21 +
   36.22 +#ifndef VMATH_H_
   36.23 +#define VMATH_H_
   36.24 +
   36.25 +#include <math.h>
   36.26 +#include "vmath_types.h"
   36.27 +
   36.28 +#ifndef M_PI
   36.29 +#define M_PI	PI
   36.30 +#endif
   36.31 +
   36.32 +#ifndef M_E
   36.33 +#define M_E				2.718281828459045
   36.34 +#endif
   36.35 +
   36.36 +#define PI				3.141592653589793
   36.37 +#define HALF_PI			1.570796326794897
   36.38 +#define QUARTER_PI		0.785398163397448
   36.39 +#define TWO_PI			6.283185307179586
   36.40 +
   36.41 +
   36.42 +#define RAD_TO_DEG(a) ((((scalar_t)a) * 360.0) / TWO_PI)
   36.43 +#define DEG_TO_RAD(a) (((scalar_t)a) * (PI / 180.0))
   36.44 +
   36.45 +#define SQ(x) ((x) * (x))
   36.46 +
   36.47 +#define MIN(a, b)	((a) < (b) ? (a) : (b))
   36.48 +#define MAX(a, b)	((a) > (b) ? (a) : (b))
   36.49 +
   36.50 +#ifndef __GNUC__
   36.51 +#define round(x)	((x) >= 0 ? (x) + 0.5 : (x) - 0.5)
   36.52 +#endif
   36.53 +
   36.54 +#ifdef __cplusplus
   36.55 +extern "C" {
   36.56 +#endif	/* __cplusplus */
   36.57 +
   36.58 +static inline scalar_t smoothstep(float a, float b, float x);
   36.59 +
   36.60 +static inline scalar_t frand(scalar_t range);
   36.61 +static inline vec3_t sphrand(scalar_t rad);
   36.62 +
   36.63 +scalar_t integral(scalar_t (*f)(scalar_t), scalar_t low, scalar_t high, int samples);
   36.64 +scalar_t gaussian(scalar_t x, scalar_t mean, scalar_t sdev);
   36.65 +
   36.66 +static inline scalar_t lerp(scalar_t a, scalar_t b, scalar_t t);
   36.67 +
   36.68 +scalar_t bspline(scalar_t a, scalar_t b, scalar_t c, scalar_t d, scalar_t t);
   36.69 +scalar_t spline(scalar_t a, scalar_t b, scalar_t c, scalar_t d, scalar_t t);
   36.70 +scalar_t bezier(scalar_t a, scalar_t b, scalar_t c, scalar_t d, scalar_t t);
   36.71 +
   36.72 +scalar_t noise1(scalar_t x);
   36.73 +scalar_t noise2(scalar_t x, scalar_t y);
   36.74 +scalar_t noise3(scalar_t x, scalar_t y, scalar_t z);
   36.75 +
   36.76 +scalar_t fbm1(scalar_t x, int octaves);
   36.77 +scalar_t fbm2(scalar_t x, scalar_t y, int octaves);
   36.78 +scalar_t fbm3(scalar_t x, scalar_t y, scalar_t z, int octaves);
   36.79 +
   36.80 +scalar_t turbulence1(scalar_t x, int octaves);
   36.81 +scalar_t turbulence2(scalar_t x, scalar_t y, int octaves);
   36.82 +scalar_t turbulence3(scalar_t x, scalar_t y, scalar_t z, int octaves);
   36.83 +
   36.84 +#ifdef __cplusplus
   36.85 +}
   36.86 +#endif	/* __cplusplus */
   36.87 +
   36.88 +#include "vmath.inl"
   36.89 +
   36.90 +#include "vector.h"
   36.91 +#include "matrix.h"
   36.92 +#include "quat.h"
   36.93 +#include "sphvec.h"
   36.94 +#include "ray.h"
   36.95 +#include "geom.h"
   36.96 +
   36.97 +#endif	/* VMATH_H_ */
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/libs/vmath/vmath.inl	Sun Sep 29 08:20:19 2013 +0300
    37.3 @@ -0,0 +1,56 @@
    37.4 +/*
    37.5 +libvmath - a vector math library
    37.6 +Copyright (C) 2004-2011 John Tsiombikas <nuclear@member.fsf.org>
    37.7 +
    37.8 +This program is free software: you can redistribute it and/or modify
    37.9 +it under the terms of the GNU Lesser General Public License as published
   37.10 +by the Free Software Foundation, either version 3 of the License, or
   37.11 +(at your option) any later version.
   37.12 +
   37.13 +This program is distributed in the hope that it will be useful,
   37.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   37.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   37.16 +GNU Lesser General Public License for more details.
   37.17 +
   37.18 +You should have received a copy of the GNU Lesser General Public License
   37.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
   37.20 +*/
   37.21 +
   37.22 +#include <stdlib.h>
   37.23 +
   37.24 +static inline scalar_t smoothstep(float a, float b, float x)
   37.25 +{
   37.26 +	if(x < a) return 0.0;
   37.27 +	if(x >= b) return 1.0;
   37.28 +
   37.29 +	x = (x - a) / (b - a);
   37.30 +	return x * x * (3.0 - 2.0 * x);
   37.31 +}
   37.32 +
   37.33 +/** Generates a random number in [0, range) */
   37.34 +static inline scalar_t frand(scalar_t range)
   37.35 +{
   37.36 +	return range * (scalar_t)rand() / (scalar_t)RAND_MAX;
   37.37 +}
   37.38 +
   37.39 +/** Generates a random vector on the surface of a sphere */
   37.40 +static inline vec3_t sphrand(scalar_t rad)
   37.41 +{
   37.42 +	scalar_t u = (scalar_t)rand() / RAND_MAX;
   37.43 +	scalar_t v = (scalar_t)rand() / RAND_MAX;
   37.44 +
   37.45 +	scalar_t theta = 2.0 * M_PI * u;
   37.46 +	scalar_t phi = acos(2.0 * v - 1.0);
   37.47 +
   37.48 +	vec3_t res;
   37.49 +	res.x = rad * cos(theta) * sin(phi);
   37.50 +	res.y = rad * sin(theta) * sin(phi);
   37.51 +	res.z = rad * cos(phi);
   37.52 +	return res;
   37.53 +}
   37.54 +
   37.55 +/** linear interpolation */
   37.56 +static inline scalar_t lerp(scalar_t a, scalar_t b, scalar_t t)
   37.57 +{
   37.58 +	return a + (b - a) * t;
   37.59 +}
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/libs/vmath/vmath_config.h	Sun Sep 29 08:20:19 2013 +0300
    38.3 @@ -0,0 +1,19 @@
    38.4 +#ifndef VMATH_CONFIG_H_
    38.5 +#define VMATH_CONFIG_H_
    38.6 +
    38.7 +#if (__STDC_VERSION__ < 199999)
    38.8 +#if defined(__GNUC__) || defined(_MSC_VER)
    38.9 +#define inline __inline
   38.10 +#else
   38.11 +#define inline
   38.12 +
   38.13 +#ifdef VECTOR_H_
   38.14 +#warning "compiling vector operations without inline, performance might suffer"
   38.15 +#endif	/* VECTOR_H_ */
   38.16 +
   38.17 +#endif	/* gcc/msvc */
   38.18 +#endif	/* not C99 */
   38.19 +
   38.20 +#define SINGLE_PRECISION_MATH
   38.21 +
   38.22 +#endif	/* VMATH_CONFIG_H_ */
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/libs/vmath/vmath_types.h	Sun Sep 29 08:20:19 2013 +0300
    39.3 @@ -0,0 +1,58 @@
    39.4 +/*
    39.5 +libvmath - a vector math library
    39.6 +Copyright (C) 2004-2011 John Tsiombikas <nuclear@member.fsf.org>
    39.7 +
    39.8 +This program is free software: you can redistribute it and/or modify
    39.9 +it under the terms of the GNU Lesser General Public License as published
   39.10 +by the Free Software Foundation, either version 3 of the License, or
   39.11 +(at your option) any later version.
   39.12 +
   39.13 +This program is distributed in the hope that it will be useful,
   39.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   39.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   39.16 +GNU Lesser General Public License for more details.
   39.17 +
   39.18 +You should have received a copy of the GNU Lesser General Public License
   39.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
   39.20 +*/
   39.21 +
   39.22 +#ifndef VMATH_TYPES_H_
   39.23 +#define VMATH_TYPES_H_
   39.24 +
   39.25 +#include "vmath_config.h"
   39.26 +
   39.27 +#define SMALL_NUMBER	1.e-4
   39.28 +#define XSMALL_NUMBER	1.e-8
   39.29 +#define ERROR_MARGIN	1.e-6
   39.30 +
   39.31 +
   39.32 +#ifdef SINGLE_PRECISION_MATH
   39.33 +typedef float scalar_t;
   39.34 +#else
   39.35 +typedef double scalar_t;
   39.36 +#endif	/* floating point precision */
   39.37 +
   39.38 +/* vectors */
   39.39 +typedef struct { scalar_t x, y; } vec2_t;
   39.40 +typedef struct { scalar_t x, y, z; } vec3_t;
   39.41 +typedef struct { scalar_t x, y, z, w; } vec4_t;
   39.42 +
   39.43 +/* quaternions */
   39.44 +typedef vec4_t quat_t;
   39.45 +
   39.46 +/* matrices */
   39.47 +typedef scalar_t mat3_t[3][3];
   39.48 +typedef scalar_t mat4_t[4][4];
   39.49 +
   39.50 +
   39.51 +#ifdef __cplusplus
   39.52 +class Vector2;
   39.53 +class Vector3;
   39.54 +class Vector4;
   39.55 +class Quaternion;
   39.56 +class Matrix3x3;
   39.57 +class Matrix4x4;
   39.58 +class SphVector;
   39.59 +#endif	/* __cplusplus */
   39.60 +
   39.61 +#endif	/* VMATH_TYPES_H_ */
    40.1 --- a/src/goat3d.cc	Sat Sep 28 20:36:55 2013 +0300
    40.2 +++ b/src/goat3d.cc	Sun Sep 29 08:20:19 2013 +0300
    40.3 @@ -25,6 +25,7 @@
    40.4  struct goat3d *goat3d_create(void)
    40.5  {
    40.6  	goat3d *goat = new goat3d;
    40.7 +	goat->flags = 0;
    40.8  	goat->scn = new Scene;
    40.9  	return goat;
   40.10  }
   40.11 @@ -142,6 +143,11 @@
   40.12  }
   40.13  
   40.14  // ---- materials ----
   40.15 +void goat3d_add_mtl(struct goat3d *g, struct goat3d_material *mtl)
   40.16 +{
   40.17 +	g->scn->add_material(mtl);
   40.18 +}
   40.19 +
   40.20  struct goat3d_material *goat3d_create_mtl(void)
   40.21  {
   40.22  	return new goat3d_material;
   40.23 @@ -197,12 +203,27 @@
   40.24  	return (*mtl)[attrib].map.c_str();
   40.25  }
   40.26  
   40.27 -void goat3d_add_mtl(struct goat3d *g, struct goat3d_material *mtl)
   40.28 +// ---- meshes ----
   40.29 +void goat3d_add_mesh(struct goat3d *g, struct goat3d_mesh *mesh)
   40.30  {
   40.31 -	g->scn->add_material(mtl);
   40.32 +	g->scn->add_mesh(mesh);
   40.33  }
   40.34  
   40.35 -// ---- meshes ----
   40.36 +int goat3d_get_mesh_count(struct goat3d *g)
   40.37 +{
   40.38 +	return g->scn->get_mesh_count();
   40.39 +}
   40.40 +
   40.41 +struct goat3d_mesh *goat3d_get_mesh(struct goat3d *g, int idx)
   40.42 +{
   40.43 +	return (goat3d_mesh*)g->scn->get_mesh(idx);
   40.44 +}
   40.45 +
   40.46 +struct goat3d_mesh *goat3d_get_mesh_by_name(struct goat3d *g, const char *name)
   40.47 +{
   40.48 +	return (goat3d_mesh*)g->scn->get_mesh(name);
   40.49 +}
   40.50 +
   40.51  struct goat3d_mesh *goat3d_create_mesh(void)
   40.52  {
   40.53  	return new goat3d_mesh;
   40.54 @@ -459,23 +480,92 @@
   40.55  	im_use[GOAT3D_MESH_ATTR_COLOR] = true;
   40.56  }
   40.57  
   40.58 -void goat3d_add_mesh(struct goat3d *g, struct goat3d_mesh *mesh)
   40.59 +/* lights */
   40.60 +void goat3d_add_light(struct goat3d *g, struct goat3d_light *lt)
   40.61  {
   40.62 -	g->scn->add_mesh(mesh);
   40.63 +	g->scn->add_light(lt);
   40.64  }
   40.65  
   40.66 -int goat3d_get_mesh_count(struct goat3d *g)
   40.67 +int goat3d_get_light_count(struct goat3d *g)
   40.68  {
   40.69 -	return g->scn->get_mesh_count();
   40.70 +	return g->scn->get_light_count();
   40.71  }
   40.72  
   40.73 -struct goat3d_mesh *goat3d_get_mesh(struct goat3d *g, int idx)
   40.74 +struct goat3d_light *goat3d_get_light(struct goat3d *g, int idx)
   40.75  {
   40.76 -	return (goat3d_mesh*)g->scn->get_mesh(idx);
   40.77 +	return (goat3d_light*)g->scn->get_light(idx);
   40.78  }
   40.79  
   40.80 +struct goat3d_light *goat3d_get_light_by_name(struct goat3d *g, const char *name)
   40.81 +{
   40.82 +	return (goat3d_light*)g->scn->get_light(name);
   40.83 +}
   40.84 +
   40.85 +
   40.86 +struct goat3d_light *goat3d_create_light(void)
   40.87 +{
   40.88 +	return new goat3d_light;
   40.89 +}
   40.90 +
   40.91 +void goat3d_destroy_light(struct goat3d_light *lt)
   40.92 +{
   40.93 +	delete lt;
   40.94 +}
   40.95 +
   40.96 +
   40.97 +/* cameras */
   40.98 +void goat3d_add_camera(struct goat3d *g, struct goat3d_camera *cam)
   40.99 +{
  40.100 +	g->scn->add_camera(cam);
  40.101 +}
  40.102 +
  40.103 +int goat3d_get_camera_count(struct goat3d *g)
  40.104 +{
  40.105 +	return g->scn->get_camera_count();
  40.106 +}
  40.107 +
  40.108 +struct goat3d_camera *goat3d_get_camera(struct goat3d *g, int idx)
  40.109 +{
  40.110 +	return (goat3d_camera*)g->scn->get_camera(idx);
  40.111 +}
  40.112 +
  40.113 +struct goat3d_camera *goat3d_get_camera_by_name(struct goat3d *g, const char *name)
  40.114 +{
  40.115 +	return (goat3d_camera*)g->scn->get_camera(name);
  40.116 +}
  40.117 +
  40.118 +struct goat3d_camera *goat3d_create_camera(void)
  40.119 +{
  40.120 +	return new goat3d_camera;
  40.121 +}
  40.122 +
  40.123 +void goat3d_destroy_camera(struct goat3d_camera *cam)
  40.124 +{
  40.125 +	delete cam;
  40.126 +}
  40.127 +
  40.128 +
  40.129  
  40.130  // node
  40.131 +void goat3d_add_node(struct goat3d *g, struct goat3d_node *node)
  40.132 +{
  40.133 +	g->scn->add_node(node);
  40.134 +}
  40.135 +
  40.136 +int goat3d_get_node_count(struct goat3d *g)
  40.137 +{
  40.138 +	return g->scn->get_node_count();
  40.139 +}
  40.140 +
  40.141 +struct goat3d_node *goat3d_get_node(struct goat3d *g, int idx)
  40.142 +{
  40.143 +	return (goat3d_node*)g->scn->get_node(idx);
  40.144 +}
  40.145 +
  40.146 +struct goat3d_node *goat3d_get_node_by_name(struct goat3d *g, const char *name)
  40.147 +{
  40.148 +	return (goat3d_node*)g->scn->get_node(name);
  40.149 +}
  40.150  
  40.151  struct goat3d_node *goat3d_create_node(void)
  40.152  {
    41.1 --- a/src/goat3d.h	Sat Sep 28 20:36:55 2013 +0300
    41.2 +++ b/src/goat3d.h	Sun Sep 29 08:20:19 2013 +0300
    41.3 @@ -90,6 +90,8 @@
    41.4  const float *goat3d_get_ambient(const struct goat3d *g);
    41.5  
    41.6  /* materials */
    41.7 +void goat3d_add_mtl(struct goat3d *g, struct goat3d_material *mtl);
    41.8 +
    41.9  struct goat3d_material *goat3d_create_mtl(void);
   41.10  void goat3d_destroy_mtl(struct goat3d_material *mtl);
   41.11  
   41.12 @@ -105,9 +107,12 @@
   41.13  void goat3d_set_mtl_attrib_map(struct goat3d_material *mtl, const char *attrib, const char *mapname);
   41.14  const char *goat3d_get_mtl_attrib_map(struct goat3d_material *mtl, const char *attrib);
   41.15  
   41.16 -void goat3d_add_mtl(struct goat3d *g, struct goat3d_material *mtl);
   41.17 +/* meshes */
   41.18 +void goat3d_add_mesh(struct goat3d *g, struct goat3d_mesh *mesh);
   41.19 +int goat3d_get_mesh_count(struct goat3d *g);
   41.20 +struct goat3d_mesh *goat3d_get_mesh(struct goat3d *g, int idx);
   41.21 +struct goat3d_mesh *goat3d_get_mesh_by_name(struct goat3d *g, const char *name);
   41.22  
   41.23 -/* meshes */
   41.24  struct goat3d_mesh *goat3d_create_mesh(void);
   41.25  void goat3d_destroy_mesh(struct goat3d_mesh *mesh);
   41.26  
   41.27 @@ -160,13 +165,32 @@
   41.28  void goat3d_color3f(float x, float y, float z);
   41.29  void goat3d_color4f(float x, float y, float z, float w);
   41.30  
   41.31 -void goat3d_add_mesh(struct goat3d *g, struct goat3d_mesh *mesh);
   41.32 +/* lights */
   41.33 +void goat3d_add_light(struct goat3d *g, struct goat3d_light *lt);
   41.34 +int goat3d_get_light_count(struct goat3d *g);
   41.35 +struct goat3d_light *goat3d_get_light(struct goat3d *g, int idx);
   41.36 +struct goat3d_light *goat3d_get_light_by_name(struct goat3d *g, const char *name);
   41.37  
   41.38 -int goat3d_get_mesh_count(struct goat3d *g);
   41.39 -struct goat3d_mesh *goat3d_get_mesh(struct goat3d *g, int idx);
   41.40 +struct goat3d_light *goat3d_create_light(void);
   41.41 +void goat3d_destroy_light(struct goat3d_light *lt);
   41.42 +
   41.43 +/* cameras */
   41.44 +void goat3d_add_camera(struct goat3d *g, struct goat3d_camera *cam);
   41.45 +int goat3d_get_camera_count(struct goat3d *g);
   41.46 +struct goat3d_camera *goat3d_get_camera(struct goat3d *g, int idx);
   41.47 +struct goat3d_camera *goat3d_get_camera_by_name(struct goat3d *g, const char *name);
   41.48 +
   41.49 +struct goat3d_camera *goat3d_create_camera(void);
   41.50 +void goat3d_destroy_camera(struct goat3d_camera *cam);
   41.51  
   41.52  /* nodes */
   41.53 +void goat3d_add_node(struct goat3d *g, struct goat3d_node *node);
   41.54 +int goat3d_get_node_count(struct goat3d *g);
   41.55 +struct goat3d_node *goat3d_get_node(struct goat3d *g, int idx);
   41.56 +struct goat3d_node *goat3d_get_node_by_name(struct goat3d *g, const char *name);
   41.57 +
   41.58  struct goat3d_node *goat3d_create_node(void);
   41.59 +void goat3d_destroy_node(struct goat3d_node *node);
   41.60  
   41.61  void goat3d_set_node_name(struct goat3d_node *node, const char *name);
   41.62  const char *goat3d_get_node_name(const struct goat3d_node *node);