conworlds
changeset 13:283cdfa7dda2
added a crapload of code from goat3dgfx
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 24 Aug 2014 09:41:24 +0300 |
parents | 778ed91cb7fd |
children | 423d4e6728cb |
files | Makefile conworlds.sln conworlds.vcxproj conworlds.vcxproj.filters src/assload.cc src/assload.h src/dataset.h src/dataset.inl src/game.cc src/gameopt.cc src/gameopt.h src/geom.cc src/geom.h src/light.cc src/light.h src/logger.cc src/logger.h src/main.cc src/material.cc src/material.h src/mesh.cc src/mesh.h src/object.cc src/object.h src/scene.cc src/scene.h src/shader.cc src/shader.h src/texture.cc src/texture.h src/unistate.cc src/unistate.h src/xform_node.cc src/xform_node.h vrchess.sln vrchess.vcxproj vrchess.vcxproj.filters |
diffstat | 37 files changed, 5398 insertions(+), 274 deletions(-) [+] |
line diff
1.1 --- a/Makefile Sat Aug 23 12:03:29 2014 +0300 1.2 +++ b/Makefile Sun Aug 24 09:41:24 2014 +0300 1.3 @@ -2,7 +2,7 @@ 1.4 ccsrc = $(wildcard src/*.cc) 1.5 obj = $(csrc:.c=.o) $(ccsrc:.cc=.o) 1.6 dep = $(obj:.o=.d) 1.7 -bin = vrchess 1.8 +bin = conworlds 1.9 1.10 # comment out to disable LibOVR (oculus sdk) 1.11 #ovr_cflags = -DUSE_LIBOVR 1.12 @@ -13,7 +13,7 @@ 1.13 1.14 CFLAGS = -pedantic -Wall -g $(ovr_cflags) 1.15 CXXFLAGS = -std=c++11 $(CFLAGS) 1.16 -LDFLAGS = $(libgl_$(sys)) -lm -lvmath -limago $(ovr_libs) 1.17 +LDFLAGS = $(libgl_$(sys)) -lm -lvmath -limago -lanim $(ovr_libs) 1.18 1.19 libgl_unix = -lGL -lGLU -lglut -lGLEW 1.20 libgl_mac = -framework OpenGL -framework GLUT -lGLEW
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/conworlds.sln Sun Aug 24 09:41:24 2014 +0300 2.3 @@ -0,0 +1,20 @@ 2.4 + 2.5 +Microsoft Visual Studio Solution File, Format Version 12.00 2.6 +# Visual Studio 2012 2.7 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "conworlds", "conworlds.vcxproj", "{714906B6-FD4C-4ECC-990C-247FA46B8801}" 2.8 +EndProject 2.9 +Global 2.10 + GlobalSection(SolutionConfigurationPlatforms) = preSolution 2.11 + Debug|Win32 = Debug|Win32 2.12 + Release|Win32 = Release|Win32 2.13 + EndGlobalSection 2.14 + GlobalSection(ProjectConfigurationPlatforms) = postSolution 2.15 + {714906B6-FD4C-4ECC-990C-247FA46B8801}.Debug|Win32.ActiveCfg = Debug|Win32 2.16 + {714906B6-FD4C-4ECC-990C-247FA46B8801}.Debug|Win32.Build.0 = Debug|Win32 2.17 + {714906B6-FD4C-4ECC-990C-247FA46B8801}.Release|Win32.ActiveCfg = Release|Win32 2.18 + {714906B6-FD4C-4ECC-990C-247FA46B8801}.Release|Win32.Build.0 = Release|Win32 2.19 + EndGlobalSection 2.20 + GlobalSection(SolutionProperties) = preSolution 2.21 + HideSolutionNode = FALSE 2.22 + EndGlobalSection 2.23 +EndGlobal
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/conworlds.vcxproj Sun Aug 24 09:41:24 2014 +0300 3.3 @@ -0,0 +1,117 @@ 3.4 +<?xml version="1.0" encoding="utf-8"?> 3.5 +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 3.6 + <ItemGroup Label="ProjectConfigurations"> 3.7 + <ProjectConfiguration Include="Debug|Win32"> 3.8 + <Configuration>Debug</Configuration> 3.9 + <Platform>Win32</Platform> 3.10 + </ProjectConfiguration> 3.11 + <ProjectConfiguration Include="Release|Win32"> 3.12 + <Configuration>Release</Configuration> 3.13 + <Platform>Win32</Platform> 3.14 + </ProjectConfiguration> 3.15 + </ItemGroup> 3.16 + <PropertyGroup Label="Globals"> 3.17 + <ProjectGuid>{714906B6-FD4C-4ECC-990C-247FA46B8801}</ProjectGuid> 3.18 + <Keyword>Win32Proj</Keyword> 3.19 + <RootNamespace>conworlds</RootNamespace> 3.20 + </PropertyGroup> 3.21 + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> 3.22 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> 3.23 + <ConfigurationType>Application</ConfigurationType> 3.24 + <UseDebugLibraries>true</UseDebugLibraries> 3.25 + <PlatformToolset>v120</PlatformToolset> 3.26 + <CharacterSet>MultiByte</CharacterSet> 3.27 + </PropertyGroup> 3.28 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> 3.29 + <ConfigurationType>Application</ConfigurationType> 3.30 + <UseDebugLibraries>false</UseDebugLibraries> 3.31 + <PlatformToolset>v120</PlatformToolset> 3.32 + <WholeProgramOptimization>false</WholeProgramOptimization> 3.33 + <CharacterSet>MultiByte</CharacterSet> 3.34 + </PropertyGroup> 3.35 + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> 3.36 + <ImportGroup Label="ExtensionSettings"> 3.37 + </ImportGroup> 3.38 + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> 3.39 + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 3.40 + </ImportGroup> 3.41 + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> 3.42 + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 3.43 + </ImportGroup> 3.44 + <PropertyGroup Label="UserMacros" /> 3.45 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> 3.46 + <LinkIncremental>true</LinkIncremental> 3.47 + </PropertyGroup> 3.48 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> 3.49 + <LinkIncremental>false</LinkIncremental> 3.50 + </PropertyGroup> 3.51 + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> 3.52 + <ClCompile> 3.53 + <PrecompiledHeader> 3.54 + </PrecompiledHeader> 3.55 + <WarningLevel>Level3</WarningLevel> 3.56 + <Optimization>Disabled</Optimization> 3.57 + <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);USE_LIBOVR</PreprocessorDefinitions> 3.58 + <DisableSpecificWarnings>4996;4244;4305</DisableSpecificWarnings> 3.59 + <AdditionalIncludeDirectories>$(SolutionDir)\src</AdditionalIncludeDirectories> 3.60 + </ClCompile> 3.61 + <Link> 3.62 + <SubSystem>Console</SubSystem> 3.63 + <GenerateDebugInformation>true</GenerateDebugInformation> 3.64 + <AdditionalDependencies>opengl32.lib;freeglutd.lib;glew32.lib;libvmath.lib;libimago2.lib;jpeglib.lib;libpng.lib;zlib.lib;libovrd.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies> 3.65 + </Link> 3.66 + </ItemDefinitionGroup> 3.67 + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> 3.68 + <ClCompile> 3.69 + <WarningLevel>Level3</WarningLevel> 3.70 + <PrecompiledHeader> 3.71 + </PrecompiledHeader> 3.72 + <Optimization>MaxSpeed</Optimization> 3.73 + <FunctionLevelLinking>true</FunctionLevelLinking> 3.74 + <IntrinsicFunctions>true</IntrinsicFunctions> 3.75 + <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);USE_LIBOVR</PreprocessorDefinitions> 3.76 + <DisableSpecificWarnings>4996;4244;4305</DisableSpecificWarnings> 3.77 + <AdditionalIncludeDirectories>$(SolutionDir)\src</AdditionalIncludeDirectories> 3.78 + </ClCompile> 3.79 + <Link> 3.80 + <SubSystem>Console</SubSystem> 3.81 + <GenerateDebugInformation>true</GenerateDebugInformation> 3.82 + <EnableCOMDATFolding>true</EnableCOMDATFolding> 3.83 + <OptimizeReferences>true</OptimizeReferences> 3.84 + <AdditionalDependencies>opengl32.lib;freeglut.lib;glew32.lib;libvmath.lib;libimago2.lib;jpeglib.lib;libpng.lib;zlib.lib;libovr.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies> 3.85 + </Link> 3.86 + </ItemDefinitionGroup> 3.87 + <ItemGroup> 3.88 + <ClCompile Include="src\camera.cc" /> 3.89 + <ClCompile Include="src\game.cc" /> 3.90 + <ClCompile Include="src\image.cc" /> 3.91 + <ClCompile Include="src\main.cc" /> 3.92 + <ClCompile Include="src\opengl.cc" /> 3.93 + <ClCompile Include="src\sdr.c" /> 3.94 + <ClCompile Include="src\texture.cc" /> 3.95 + <ClCompile Include="src\vr\mathutil.c" /> 3.96 + <ClCompile Include="src\vr\opt.c" /> 3.97 + <ClCompile Include="src\vr\rbtree.c" /> 3.98 + <ClCompile Include="src\vr\vr.c" /> 3.99 + <ClCompile Include="src\vr\vr_libovr.c" /> 3.100 + <ClCompile Include="src\vr\vr_modules.c" /> 3.101 + <ClCompile Include="src\vr\vr_null.c" /> 3.102 + <ClCompile Include="src\vr\vr_openhmd.c" /> 3.103 + </ItemGroup> 3.104 + <ItemGroup> 3.105 + <ClInclude Include="src\camera.h" /> 3.106 + <ClInclude Include="src\game.h" /> 3.107 + <ClInclude Include="src\image.h" /> 3.108 + <ClInclude Include="src\opengl.h" /> 3.109 + <ClInclude Include="src\sdr.h" /> 3.110 + <ClInclude Include="src\texture.h" /> 3.111 + <ClInclude Include="src\vr\mathutil.h" /> 3.112 + <ClInclude Include="src\vr\opt.h" /> 3.113 + <ClInclude Include="src\vr\rbtree.h" /> 3.114 + <ClInclude Include="src\vr\vr.h" /> 3.115 + <ClInclude Include="src\vr\vr_impl.h" /> 3.116 + </ItemGroup> 3.117 + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> 3.118 + <ImportGroup Label="ExtensionTargets"> 3.119 + </ImportGroup> 3.120 +</Project>
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/conworlds.vcxproj.filters Sun Aug 24 09:41:24 2014 +0300 4.3 @@ -0,0 +1,94 @@ 4.4 +<?xml version="1.0" encoding="utf-8"?> 4.5 +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 4.6 + <ItemGroup> 4.7 + <Filter Include="src"> 4.8 + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> 4.9 + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;h;inl</Extensions> 4.10 + </Filter> 4.11 + <Filter Include="src\vr"> 4.12 + <UniqueIdentifier>{e881ab02-1a45-43f6-a15d-ee7f77256a1e}</UniqueIdentifier> 4.13 + </Filter> 4.14 + </ItemGroup> 4.15 + <ItemGroup> 4.16 + <ClCompile Include="src\main.cc"> 4.17 + <Filter>src</Filter> 4.18 + </ClCompile> 4.19 + <ClCompile Include="src\camera.cc"> 4.20 + <Filter>src</Filter> 4.21 + </ClCompile> 4.22 + <ClCompile Include="src\opengl.cc"> 4.23 + <Filter>src</Filter> 4.24 + </ClCompile> 4.25 + <ClCompile Include="src\sdr.c"> 4.26 + <Filter>src</Filter> 4.27 + </ClCompile> 4.28 + <ClCompile Include="src\game.cc"> 4.29 + <Filter>src</Filter> 4.30 + </ClCompile> 4.31 + <ClCompile Include="src\image.cc"> 4.32 + <Filter>src</Filter> 4.33 + </ClCompile> 4.34 + <ClCompile Include="src\texture.cc"> 4.35 + <Filter>src</Filter> 4.36 + </ClCompile> 4.37 + <ClCompile Include="src\vr\vr.c"> 4.38 + <Filter>src\vr</Filter> 4.39 + </ClCompile> 4.40 + <ClCompile Include="src\vr\vr_libovr.c"> 4.41 + <Filter>src\vr</Filter> 4.42 + </ClCompile> 4.43 + <ClCompile Include="src\vr\vr_modules.c"> 4.44 + <Filter>src\vr</Filter> 4.45 + </ClCompile> 4.46 + <ClCompile Include="src\vr\vr_null.c"> 4.47 + <Filter>src\vr</Filter> 4.48 + </ClCompile> 4.49 + <ClCompile Include="src\vr\rbtree.c"> 4.50 + <Filter>src\vr</Filter> 4.51 + </ClCompile> 4.52 + <ClCompile Include="src\vr\opt.c"> 4.53 + <Filter>src\vr</Filter> 4.54 + </ClCompile> 4.55 + <ClCompile Include="src\vr\vr_openhmd.c"> 4.56 + <Filter>src\vr</Filter> 4.57 + </ClCompile> 4.58 + <ClCompile Include="src\vr\mathutil.c"> 4.59 + <Filter>src\vr</Filter> 4.60 + </ClCompile> 4.61 + </ItemGroup> 4.62 + <ItemGroup> 4.63 + <ClInclude Include="src\camera.h"> 4.64 + <Filter>src</Filter> 4.65 + </ClInclude> 4.66 + <ClInclude Include="src\game.h"> 4.67 + <Filter>src</Filter> 4.68 + </ClInclude> 4.69 + <ClInclude Include="src\image.h"> 4.70 + <Filter>src</Filter> 4.71 + </ClInclude> 4.72 + <ClInclude Include="src\opengl.h"> 4.73 + <Filter>src</Filter> 4.74 + </ClInclude> 4.75 + <ClInclude Include="src\sdr.h"> 4.76 + <Filter>src</Filter> 4.77 + </ClInclude> 4.78 + <ClInclude Include="src\texture.h"> 4.79 + <Filter>src</Filter> 4.80 + </ClInclude> 4.81 + <ClInclude Include="src\vr\vr.h"> 4.82 + <Filter>src\vr</Filter> 4.83 + </ClInclude> 4.84 + <ClInclude Include="src\vr\vr_impl.h"> 4.85 + <Filter>src\vr</Filter> 4.86 + </ClInclude> 4.87 + <ClInclude Include="src\vr\rbtree.h"> 4.88 + <Filter>src\vr</Filter> 4.89 + </ClInclude> 4.90 + <ClInclude Include="src\vr\opt.h"> 4.91 + <Filter>src\vr</Filter> 4.92 + </ClInclude> 4.93 + <ClInclude Include="src\vr\mathutil.h"> 4.94 + <Filter>src\vr</Filter> 4.95 + </ClInclude> 4.96 + </ItemGroup> 4.97 +</Project> 4.98 \ No newline at end of file
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/assload.cc Sun Aug 24 09:41:24 2014 +0300 5.3 @@ -0,0 +1,437 @@ 5.4 +#include <stdio.h> 5.5 +#include "assload.h" 5.6 +#include "logger.h" 5.7 + 5.8 +#ifdef USE_ASSIMP 5.9 + 5.10 +#include <vector> 5.11 +#include <map> 5.12 +#include "assimp/cimport.h" 5.13 +#include "assimp/scene.h" 5.14 +#include "assimp/postprocess.h" 5.15 +#include "texman.h" 5.16 +#include "material.h" 5.17 +#include "scene.h" 5.18 + 5.19 +using namespace std; 5.20 + 5.21 +static bool load_material(Material *mat, const aiMaterial *aimat); 5.22 +static Object *load_node(const aiScene *aiscn, const aiNode *ainode); 5.23 +static Mesh *load_mesh(const aiScene *aiscn, const aiMesh *aimesh); 5.24 +static Curve *load_curve(const aiScene *aiscn, const aiMesh *aimesh); 5.25 +static bool load_bones(Mesh *mesh, const aiMesh *aimesh); 5.26 + 5.27 +static Vector3 assimp_vector(const aiVector3D &v); 5.28 +static Quaternion assimp_quat(const aiQuaternion &q); 5.29 +static Matrix4x4 assimp_matrix(const aiMatrix4x4 &aim); 5.30 +static long assimp_time(const aiAnimation *anim, double aitime); 5.31 +static void print_hierarchy(const aiNode *node); 5.32 + 5.33 +static map<string, Object*> obj_by_name; 5.34 +static map<aiMesh*, Mesh*> mesh_by_aimesh; 5.35 + 5.36 +bool load_ass(Scene *scn, const char *fname) 5.37 +{ 5.38 + static bool init_done; 5.39 + 5.40 + if(!init_done) { 5.41 + static aiLogStream log_stream = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT, 0); 5.42 + aiAttachLogStream(&log_stream); 5.43 + //aiEnableVerboseLogging(1); 5.44 + init_done = true; 5.45 + } 5.46 + 5.47 + unsigned int proc_flags = aiProcess_JoinIdenticalVertices | 5.48 + aiProcess_CalcTangentSpace | 5.49 + aiProcess_Triangulate | 5.50 + aiProcess_SortByPType | 5.51 + aiProcess_FlipUVs; 5.52 + 5.53 + const aiScene *aiscn = aiImportFile(datafile_path(fname).c_str(), proc_flags); 5.54 + if(!aiscn) { 5.55 + error_log("failed to load file: %s\n", fname); 5.56 + return false; 5.57 + } 5.58 + 5.59 + info_log("NODE HIERARCHY:\n"); 5.60 + print_hierarchy(aiscn->mRootNode); 5.61 + info_log("-------------------\n"); 5.62 + 5.63 + Vector3 root_pos, root_scaling(1.0, 1.0, 1.0); 5.64 + Quaternion root_rot; 5.65 + 5.66 + if(aiscn->mRootNode) { 5.67 + Matrix4x4 root_matrix = assimp_matrix(aiscn->mRootNode->mTransformation); 5.68 + root_pos = root_matrix.get_translation(); 5.69 + root_rot = root_matrix.get_rotation_quat(); 5.70 + root_scaling = root_matrix.get_scaling(); 5.71 + } 5.72 + 5.73 + // load all meshes 5.74 + for(unsigned int i=0; i<aiscn->mNumMeshes; i++) { 5.75 + aiMesh *aimesh = aiscn->mMeshes[i]; 5.76 + Mesh *mesh; 5.77 + Curve *curve; 5.78 + 5.79 + switch(aimesh->mPrimitiveTypes) { 5.80 + case aiPrimitiveType_TRIANGLE: 5.81 + if((mesh = load_mesh(aiscn, aimesh))) { 5.82 + mesh_by_aimesh[aimesh] = mesh; 5.83 + scn->meshes.push_back(mesh); 5.84 + } 5.85 + break; 5.86 + 5.87 + case aiPrimitiveType_LINE: 5.88 + if((curve = load_curve(aiscn, aimesh))) { 5.89 + scn->curves.push_back(curve); 5.90 + } 5.91 + break; 5.92 + 5.93 + default: 5.94 + error_log("unsupported primitive type: %u\n", aimesh->mPrimitiveTypes); 5.95 + break; 5.96 + } 5.97 + } 5.98 + 5.99 + // load all the nodes recursively 5.100 + for(unsigned int i=0; i<aiscn->mRootNode->mNumChildren; i++) { 5.101 + Object *obj = load_node(aiscn, aiscn->mRootNode->mChildren[i]); 5.102 + if(obj) { 5.103 + Object *dummy = new Object; 5.104 + dummy->set_name((string("dummyroot_") + string(obj->get_name())).c_str()); 5.105 + dummy->set_position(root_pos); 5.106 + dummy->set_rotation(root_rot); 5.107 + dummy->set_scaling(root_scaling); 5.108 + dummy->add_child(obj); 5.109 + 5.110 + obj = dummy; 5.111 + scn->objects.push_back(obj); 5.112 + } 5.113 + } 5.114 + 5.115 + // load and attach the bones to the meshes 5.116 + for(unsigned int i=0; i<aiscn->mNumMeshes; i++) { 5.117 + aiMesh *aimesh = aiscn->mMeshes[i]; 5.118 + 5.119 + Mesh *mesh = mesh_by_aimesh[aimesh]; 5.120 + load_bones(mesh, aimesh); 5.121 + } 5.122 + 5.123 + obj_by_name.clear(); 5.124 + mesh_by_aimesh.clear(); 5.125 + 5.126 + aiReleaseImport(aiscn); 5.127 + return true; 5.128 +} 5.129 + 5.130 +static bool load_material(Material *mat, const aiMaterial *aimat) 5.131 +{ 5.132 + aiColor4D aicol; 5.133 + float shin, shin_str; 5.134 + 5.135 + if(aiGetMaterialColor(aimat, AI_MATKEY_COLOR_DIFFUSE, &aicol) == 0) { 5.136 + mat->diffuse = Vector3(aicol[0], aicol[1], aicol[2]); 5.137 + } 5.138 + if(aiGetMaterialColor(aimat, AI_MATKEY_COLOR_SPECULAR, &aicol) == 0) { 5.139 + mat->specular = Vector3(aicol[0], aicol[1], aicol[2]); 5.140 + } 5.141 + 5.142 + unsigned int count = 1; 5.143 + if(aiGetMaterialFloatArray(aimat, AI_MATKEY_SHININESS_STRENGTH, &shin_str, &count) != 0) { 5.144 + shin_str = 1.0; 5.145 + } 5.146 + if(aiGetMaterialFloatArray(aimat, AI_MATKEY_SHININESS, &shin, &count) == 0) { 5.147 + // XXX can't remember how I came up with this... 5.148 + mat->shininess = shin * shin_str * 0.0001 * 128.0; 5.149 + } 5.150 + 5.151 + // load textures 5.152 + struct { int type; aiTextureType aitype; } textypes[] = { 5.153 + {TEX_DIFFUSE, aiTextureType_DIFFUSE}, 5.154 + {TEX_NORMAL, aiTextureType_NORMALS}, 5.155 + {TEX_SPECULAR, aiTextureType_SPECULAR} 5.156 + }; 5.157 + 5.158 + for(int i=0; i<sizeof textypes / sizeof *textypes; i++) { 5.159 + aiString aipath; 5.160 + 5.161 + if(aiGetMaterialTexture(aimat, textypes[i].aitype, 0, &aipath) == 0) { 5.162 + char *tmp, *fname = aipath.data; 5.163 + 5.164 + if((tmp = strrchr(fname, '/'))) { 5.165 + fname = tmp + 1; 5.166 + } 5.167 + if((tmp = strrchr(fname, '\\'))) { 5.168 + fname = tmp + 1; 5.169 + } 5.170 + 5.171 + if(*fname) { 5.172 + mat->tex[textypes[i].type] = texset.get(fname); 5.173 + } 5.174 + } 5.175 + } 5.176 + 5.177 + return true; 5.178 +} 5.179 + 5.180 +static Object *load_node(const aiScene *aiscn, const aiNode *ainode) 5.181 +{ 5.182 + Object *obj = new Object; 5.183 + obj->set_name(ainode->mName.data); 5.184 + 5.185 + if(ainode->mNumMeshes) { 5.186 + if(ainode->mNumMeshes > 1) { 5.187 + info_log("%s warning: node %s has more than one meshes (%u)\n", __FUNCTION__, 5.188 + ainode->mName.data, ainode->mNumMeshes); 5.189 + } 5.190 + 5.191 + aiMesh *aimesh = aiscn->mMeshes[ainode->mMeshes[0]]; 5.192 + obj->set_mesh(mesh_by_aimesh[aimesh]); 5.193 + 5.194 + // also grab the material of this mesh 5.195 + load_material(&obj->material, aiscn->mMaterials[aimesh->mMaterialIndex]); 5.196 + } 5.197 + 5.198 + // if there are animations, grab the first and try to use it 5.199 + if(aiscn->mNumAnimations) { 5.200 + aiAnimation *aianim = aiscn->mAnimations[0]; 5.201 + aiNodeAnim *ainodeanim = 0; 5.202 + for(unsigned int i=0; i<aianim->mNumChannels; i++) { 5.203 + if(strcmp(aianim->mChannels[i]->mNodeName.data, ainode->mName.data) == 0) { 5.204 + ainodeanim = aianim->mChannels[i]; 5.205 + break; 5.206 + } 5.207 + } 5.208 + 5.209 + if(ainodeanim) { 5.210 + // load all position (translation) keyframes 5.211 + for(unsigned int i=0; i<ainodeanim->mNumPositionKeys; i++) { 5.212 + Vector3 pos = assimp_vector(ainodeanim->mPositionKeys[i].mValue); 5.213 + long msec = assimp_time(aianim, ainodeanim->mPositionKeys[i].mTime); 5.214 + obj->set_position(pos, msec); 5.215 + } 5.216 + 5.217 + // load all rotation keyframes 5.218 + for(unsigned int i=0; i<ainodeanim->mNumRotationKeys; i++) { 5.219 + Quaternion rot = assimp_quat(ainodeanim->mRotationKeys[i].mValue); 5.220 + if(rot.length_sq() < SMALL_NUMBER) { 5.221 + continue; 5.222 + } 5.223 + rot.normalize(); 5.224 + long msec = assimp_time(aianim, ainodeanim->mRotationKeys[i].mTime); 5.225 + obj->set_rotation(rot, msec); 5.226 + } 5.227 + 5.228 + // load all scaling keyframes 5.229 + for(unsigned int i=0; i<ainodeanim->mNumScalingKeys; i++) { 5.230 + Vector3 scale = assimp_vector(ainodeanim->mScalingKeys[i].mValue); 5.231 + long msec = assimp_time(aianim, ainodeanim->mScalingKeys[i].mTime); 5.232 + obj->set_scaling(scale, msec); 5.233 + } 5.234 + 5.235 + obj->set_extrapolator(EXTRAP_REPEAT); // loop animation 5.236 + } else { 5.237 + Matrix4x4 local_matrix = assimp_matrix(ainode->mTransformation); 5.238 + obj->set_local_matrix(local_matrix); 5.239 + } 5.240 + } 5.241 + 5.242 + /* recurse to all children */ 5.243 + for(unsigned int i=0; i<ainode->mNumChildren; i++) { 5.244 + Object *child = load_node(aiscn, ainode->mChildren[i]); 5.245 + if(child) { 5.246 + obj->add_child(child); 5.247 + } 5.248 + } 5.249 + 5.250 + obj_by_name[obj->get_name()] = obj; 5.251 + return obj; 5.252 +} 5.253 + 5.254 +static Mesh *load_mesh(const aiScene *aiscn, const aiMesh *aimesh) 5.255 +{ 5.256 + Mesh *mesh = new Mesh; 5.257 + 5.258 + int num_verts = aimesh->mNumVertices; 5.259 + int num_faces = aimesh->mNumFaces; 5.260 + 5.261 + mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, (float*)aimesh->mVertices); 5.262 + 5.263 + if(aimesh->mNormals) { 5.264 + mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, (float*)aimesh->mNormals); 5.265 + } 5.266 + if(aimesh->mTangents) { 5.267 + mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, (float*)aimesh->mTangents); 5.268 + } 5.269 + if(aimesh->mTextureCoords[0]) { 5.270 + mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 3, num_verts, (float*)aimesh->mTextureCoords[0]); 5.271 + } 5.272 + 5.273 + if(aimesh->mBones) { 5.274 + float *weights = mesh->set_attrib_data(MESH_ATTR_BONEWEIGHTS, 4, num_verts, 0); 5.275 + float *boneidx = mesh->set_attrib_data(MESH_ATTR_BONEIDX, 4, num_verts, 0); 5.276 + 5.277 + memset(weights, 0, num_verts * 4 * sizeof *weights); 5.278 + memset(boneidx, 0, num_verts * 4 * sizeof *boneidx); 5.279 + 5.280 + int *vertex_bone_count = new int[num_verts]; 5.281 + memset(vertex_bone_count, 0, num_verts * sizeof *vertex_bone_count); 5.282 + 5.283 + for(unsigned int i=0; i<aimesh->mNumBones; i++) { 5.284 + aiBone *aibone = aimesh->mBones[i]; 5.285 + 5.286 + // for every vertex affected by this bone: 5.287 + for(unsigned int j=0; j<aibone->mNumWeights; j++) { 5.288 + aiVertexWeight *aiweight = aibone->mWeights + j; 5.289 + int vidx = aiweight->mVertexId; 5.290 + int vert_boneidx = vertex_bone_count[vidx]; 5.291 + if(vert_boneidx >= 4) { 5.292 + error_log("WARNING vertex with more than 4 bones found\n"); 5.293 + continue; 5.294 + } 5.295 + 5.296 + weights[vidx * 4 + vert_boneidx] = aiweight->mWeight; 5.297 + boneidx[vidx * 4 + vert_boneidx] = (float)i; 5.298 + vertex_bone_count[vidx]++; 5.299 + } 5.300 + } 5.301 + 5.302 + delete [] vertex_bone_count; 5.303 + 5.304 + // normalize weights 5.305 + for(int i=0; i<num_verts; i++) { 5.306 + 5.307 + float wsum = 0.0f; 5.308 + 5.309 + for(int j=0; j<4; j++) { 5.310 + wsum += weights[i * 4 + j]; 5.311 + } 5.312 + 5.313 + if(1.0 - wsum > 1e-4) { 5.314 + error_log("WARNING vertex with weights < 1 (%f), normalizing...\n", wsum); 5.315 + 5.316 + if(wsum < 1e-6) { 5.317 + // this is clearly broken, let's use the first bone in full 5.318 + weights[i * 4] = 1.0; 5.319 + } else { 5.320 + weights[i * 4] /= wsum; 5.321 + weights[i * 4 + 1] /= wsum; 5.322 + weights[i * 4 + 2] /= wsum; 5.323 + weights[i * 4 + 3] /= wsum; 5.324 + } 5.325 + } 5.326 + } 5.327 + } 5.328 + 5.329 + unsigned int *iptr = mesh->set_index_data(num_faces * 3); 5.330 + for(int i=0; i<num_faces; i++) { 5.331 + for(int j=0; j<3; j++) { 5.332 + *iptr++ = aimesh->mFaces[i].mIndices[j]; 5.333 + } 5.334 + } 5.335 + 5.336 + return mesh; 5.337 +} 5.338 + 5.339 +static Curve *load_curve(const aiScene *aiscn, const aiMesh *aimesh) 5.340 +{ 5.341 + Curve *curve = new Curve; 5.342 + 5.343 + for(unsigned int i=0; i<aimesh->mNumVertices; i++) { 5.344 + Vector3 pt = assimp_vector(aimesh->mVertices[i]); 5.345 + curve->add_point(pt); 5.346 + } 5.347 + info_log("loaded curve with %d points\n", aimesh->mNumVertices); 5.348 + 5.349 + return curve; 5.350 +} 5.351 + 5.352 +static bool load_bones(Mesh *mesh, const aiMesh *aimesh) 5.353 +{ 5.354 + if(!aimesh->mNumBones) { 5.355 + return false; 5.356 + } 5.357 + 5.358 + for(unsigned int i=0; i<aimesh->mNumBones; i++) { 5.359 + aiBone *aibone = aimesh->mBones[i]; 5.360 + Object *obj = obj_by_name[aibone->mName.data]; 5.361 + if(!obj) { 5.362 + error_log("bone %s not found\n", aibone->mName.data); 5.363 + continue; 5.364 + } 5.365 + 5.366 + obj->set_bone_matrix(assimp_matrix(aibone->mOffsetMatrix)); 5.367 + mesh->add_bone(obj); 5.368 + 5.369 + info_log("adding bone: %s\n", obj->get_name()); 5.370 + } 5.371 + 5.372 + return true; 5.373 +} 5.374 + 5.375 +static Vector3 assimp_vector(const aiVector3D &v) 5.376 +{ 5.377 + return Vector3(v[0], v[1], v[2]); 5.378 +} 5.379 + 5.380 +static Quaternion assimp_quat(const aiQuaternion &q) 5.381 +{ 5.382 + return Quaternion(q.w, Vector3(q.x, q.y, q.z)); 5.383 +} 5.384 + 5.385 +static Matrix4x4 assimp_matrix(const aiMatrix4x4 &aim) 5.386 +{ 5.387 + Matrix4x4 m; 5.388 + memcpy(m[0], &aim, 16 * sizeof(float)); 5.389 + return m; 5.390 +} 5.391 + 5.392 +/* convert an assimp keyframe time (ticks) into milliseconds */ 5.393 +static long assimp_time(const aiAnimation *anim, double aitime) 5.394 +{ 5.395 + double sec; 5.396 + if(anim->mTicksPerSecond < 1e-6) { 5.397 + // assume time is in frames? 5.398 + sec = aitime / 30.0; 5.399 + } else { 5.400 + sec = aitime / anim->mTicksPerSecond; 5.401 + } 5.402 + return (long)(sec * 1000.0); 5.403 +} 5.404 + 5.405 +static void print_hierarchy(const aiNode *node) 5.406 +{ 5.407 + static int lvl; 5.408 + static int lvlopen[256]; 5.409 + 5.410 + for(int i=0; i<lvl; i++) { 5.411 + putchar(' '); 5.412 + if(lvlopen[i]) { 5.413 + putchar(i >= lvl - 1 ? '+' : '|'); 5.414 + } else { 5.415 + putchar(i >= lvl - 1 ? '+' : ' '); 5.416 + } 5.417 + } 5.418 + info_log("- \"%s\"\n", node->mName.data); 5.419 + 5.420 + lvlopen[lvl] = 1; 5.421 + 5.422 + lvl++; 5.423 + for(unsigned int i=0; i<node->mNumChildren; i++) { 5.424 + if(i == node->mNumChildren - 1) { 5.425 + lvlopen[lvl - 1] = 0; 5.426 + } 5.427 + print_hierarchy(node->mChildren[i]); 5.428 + } 5.429 + lvl--; 5.430 +} 5.431 + 5.432 +#else // !defined USE_ASSIMP 5.433 + 5.434 +bool load_ass(Scene *scn, const char *fname) 5.435 +{ 5.436 + error_log("load_ass: assimp support not compiled in\n"); 5.437 + return false; 5.438 +} 5.439 + 5.440 +#endif
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/assload.h Sun Aug 24 09:41:24 2014 +0300 6.3 @@ -0,0 +1,9 @@ 6.4 +#ifndef ASSLOAD_H_ 6.5 +#define ASSLOAD_H_ 6.6 + 6.7 +#include <vector> 6.8 +#include "scene.h" 6.9 + 6.10 +bool load_ass(Scene *scn, const char *fname); 6.11 + 6.12 +#endif // ASSLOAD_H_
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/dataset.h Sun Aug 24 09:41:24 2014 +0300 7.3 @@ -0,0 +1,44 @@ 7.4 +/** DataSet is a generic resource database with fast O(logn) lookups by name 7.5 + * it can be used for texture managers, mesh managers, sound effect managers etc 7.6 + * 7.7 + * The constructor takes a load function and a destructor function to be called 7.8 + * when a nonexistent resource is requested and needs to be loaded, and when 7.9 + * the DataSet is destroyed. The destructor is optional and can be set to null 7.10 + * if not needed. 7.11 + * 7.12 + * Requesting a resource works by simply calling get, example: 7.13 + * ---------------------------------------------------------- 7.14 + * \code 7.15 + * Texture *load_texture(const char *fname); 7.16 + * void free_texture(Texture *tex); 7.17 + * 7.18 + * DataSet<Texture*> texman(load_texture, free_texture); 7.19 + * Texture *foo = texman.get("foo.png"); 7.20 + * \endcode 7.21 + */ 7.22 +#ifndef DATASET_H_ 7.23 +#define DATASET_H_ 7.24 + 7.25 +#include <string> 7.26 +#include <map> 7.27 + 7.28 +template <typename T> 7.29 +class DataSet { 7.30 +protected: 7.31 + mutable std::map<std::string, T> data; 7.32 + 7.33 + T (*load)(const char*); 7.34 + void (*destroy)(T); 7.35 + 7.36 +public: 7.37 + DataSet(T (*load_func)(const char*), void (*destr_func)(T) = 0); 7.38 + ~DataSet(); 7.39 + 7.40 + void clear(); 7.41 + 7.42 + T get(const char *name) const; 7.43 +}; 7.44 + 7.45 +#include "dataset.inl" 7.46 + 7.47 +#endif // DATASET_H_
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/src/dataset.inl Sun Aug 24 09:41:24 2014 +0300 8.3 @@ -0,0 +1,55 @@ 8.4 +#include <stdio.h> 8.5 +#include <string.h> 8.6 + 8.7 +template <typename T> 8.8 +DataSet<T>::DataSet(T (*load_func)(const char*), void (*destr_func)(T)) 8.9 +{ 8.10 + load = load_func; 8.11 + destroy = destr_func; 8.12 +} 8.13 + 8.14 +template <typename T> 8.15 +DataSet<T>::~DataSet() 8.16 +{ 8.17 + clear(); 8.18 +} 8.19 + 8.20 +template <typename T> 8.21 +void DataSet<T>::clear() 8.22 +{ 8.23 + if(destroy) { 8.24 + typename std::map<std::string, T>::iterator it = data.begin(); 8.25 + while(it != data.end()) { 8.26 + destroy(it++->second); 8.27 + } 8.28 + } 8.29 + data.clear(); 8.30 +} 8.31 + 8.32 +template <typename T> 8.33 +T DataSet<T>::get(const char *name) const 8.34 +{ 8.35 + typename std::map<std::string, T>::const_iterator iter = data.find(name); 8.36 + if(iter != data.end()) { 8.37 + return iter->second; 8.38 + } 8.39 + 8.40 + const char *fname, *slash; 8.41 + if((slash = strrchr(name, '/'))) { 8.42 + fname = slash + 1; 8.43 + } else { 8.44 + fname = name; 8.45 + } 8.46 + 8.47 + std::string path = fname; 8.48 + if(path.empty()) { 8.49 + fprintf(stderr, "can't find data file: %s\n", name); 8.50 + return 0; 8.51 + } 8.52 + 8.53 + T res = load(path.c_str()); 8.54 + if(res) { 8.55 + data[name] = res; 8.56 + } 8.57 + return res; 8.58 +}
9.1 --- a/src/game.cc Sat Aug 23 12:03:29 2014 +0300 9.2 +++ b/src/game.cc Sun Aug 24 09:41:24 2014 +0300 9.3 @@ -1,4 +1,5 @@ 9.4 #include "game.h" 9.5 +#include "gameopt.h" 9.6 #include "opengl.h" 9.7 #include "camera.h" 9.8 #include "texture.h" 9.9 @@ -18,11 +19,18 @@ 9.10 static FlyCamera cam; 9.11 static Texture floor_tex; 9.12 static bool keystate[256]; 9.13 +static float player_height = 1.68; 9.14 9.15 bool game_init() 9.16 { 9.17 - vr_init(); 9.18 - //vr_use_module_named("null"); 9.19 + if(opt.vr) { 9.20 + vr_init(); 9.21 + if(opt.vr_module) { 9.22 + vr_use_module_named(opt.vr_module); 9.23 + } 9.24 + 9.25 + player_height = vr_get_optf(VR_OPT_EYE_HEIGHT); 9.26 + } 9.27 9.28 glEnable(GL_DEPTH_TEST); 9.29 glEnable(GL_CULL_FACE); 9.30 @@ -37,14 +45,16 @@ 9.31 return false; 9.32 } 9.33 9.34 - cam.input_move(0, 0, 5); 9.35 + cam.input_move(0, player_height, 0); 9.36 return true; 9.37 } 9.38 9.39 void game_cleanup() 9.40 { 9.41 floor_tex.destroy(); 9.42 - vr_shutdown(); 9.43 + if(opt.vr) { 9.44 + vr_shutdown(); 9.45 + } 9.46 9.47 if(fbo) { 9.48 glDeleteFramebuffers(1, &fbo); 9.49 @@ -88,24 +98,30 @@ 9.50 9.51 void game_render() 9.52 { 9.53 - glBindFramebuffer(GL_FRAMEBUFFER, fbo); 9.54 - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 9.55 + if(opt.vr) { 9.56 + glBindFramebuffer(GL_FRAMEBUFFER, fbo); 9.57 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 9.58 9.59 - glViewport(0, 0, rtwidth / 2.0, rtheight); 9.60 - vr_begin(VR_EYE_LEFT); 9.61 - game_render_eye(-1); 9.62 - vr_end(); 9.63 + glViewport(0, 0, rtwidth / 2.0, rtheight); 9.64 + vr_begin(VR_EYE_LEFT); 9.65 + game_render_eye(-1); 9.66 + vr_end(); 9.67 9.68 - glViewport(rtwidth / 2, 0, rtwidth / 2.0, rtheight); 9.69 - vr_begin(VR_EYE_RIGHT); 9.70 - game_render_eye(1); 9.71 - vr_end(); 9.72 + glViewport(rtwidth / 2, 0, rtwidth / 2.0, rtheight); 9.73 + vr_begin(VR_EYE_RIGHT); 9.74 + game_render_eye(1); 9.75 + vr_end(); 9.76 9.77 - glBindFramebuffer(GL_FRAMEBUFFER, 0); 9.78 - glViewport(0, 0, fb_width, fb_height); 9.79 + glBindFramebuffer(GL_FRAMEBUFFER, 0); 9.80 + glViewport(0, 0, fb_width, fb_height); 9.81 9.82 - vr_output_texture(rtarg->get_texture_id(), 0, 0, (float)rtwidth / (float)rtarg->get_width(), 9.83 - (float)rtheight / (float)rtarg->get_height()); 9.84 + vr_output_texture(rtarg->get_texture_id(), 0, 0, (float)rtwidth / (float)rtarg->get_width(), 9.85 + (float)rtheight / (float)rtarg->get_height()); 9.86 + } else { 9.87 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 9.88 + 9.89 + game_render_eye(0); 9.90 + } 9.91 9.92 vr_swap_buffers(); 9.93 } 9.94 @@ -218,14 +234,11 @@ 9.95 9.96 static void draw_scene() 9.97 { 9.98 - glMatrixMode(GL_MODELVIEW); 9.99 - glTranslatef(0, -1.5, 0); 9.100 - 9.101 float lpos[] = {-20, 30, 10, 1}; 9.102 glLightfv(GL_LIGHT0, GL_POSITION, lpos); 9.103 9.104 glEnable(GL_TEXTURE_2D); 9.105 - floor_tex.bind(); 9.106 + bind_texture(&floor_tex); 9.107 9.108 glMatrixMode(GL_TEXTURE); 9.109 glScalef(8, 8, 8); 9.110 @@ -251,19 +264,19 @@ 9.111 glNormal3f(0, 1, 1); 9.112 glVertex3f(-1, 0, 1); 9.113 glVertex3f(1, 0, 1); 9.114 - glVertex3f(0, 1.2, 0); 9.115 + glVertex3f(0, 1.75, 0); 9.116 glNormal3f(1, 1, 0); 9.117 glVertex3f(1, 0, 1); 9.118 glVertex3f(1, 0, -1); 9.119 - glVertex3f(0, 1.2, 0); 9.120 + glVertex3f(0, 1.75, 0); 9.121 glNormal3f(0, 1, -1); 9.122 glVertex3f(1, 0, -1); 9.123 glVertex3f(-1, 0, -1); 9.124 - glVertex3f(0, 1.2, 0); 9.125 + glVertex3f(0, 1.75, 0); 9.126 glNormal3f(-1, 1, 0); 9.127 glVertex3f(-1, 0, -1); 9.128 glVertex3f(-1, 0, 1); 9.129 - glVertex3f(0, 1.2, 0); 9.130 + glVertex3f(0, 1.75, 0); 9.131 glEnd(); 9.132 9.133 glPopMatrix();
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/src/gameopt.cc Sun Aug 24 09:41:24 2014 +0300 10.3 @@ -0,0 +1,39 @@ 10.4 +#include <stdio.h> 10.5 +#include <string.h> 10.6 +#include "gameopt.h" 10.7 + 10.8 +GameOption opt; 10.9 + 10.10 +bool parse_args(int argc, char **argv) 10.11 +{ 10.12 + int i; 10.13 + 10.14 + for(i=1; i<argc; i++) { 10.15 + if(argv[i][0] == '-') { 10.16 + if(strcmp(argv[i], "-vr") == 0) { 10.17 + opt.vr = true; 10.18 + 10.19 + } else if(strcmp(argv[i], "-vrmodule") == 0) { 10.20 + opt.vr_module = argv[++i]; 10.21 + if(strcmp(opt.vr_module, "stereo") == 0) { 10.22 + opt.stereo = true; 10.23 + } 10.24 + 10.25 + } else { 10.26 + fprintf(stderr, "invalid option: %s\n", argv[i]); 10.27 + return false; 10.28 + } 10.29 + } else { 10.30 + fprintf(stderr, "unexpected argument: %s\n", argv[i]); 10.31 + return false; 10.32 + } 10.33 + } 10.34 + return true; 10.35 +} 10.36 + 10.37 +GameOption::GameOption() 10.38 +{ 10.39 + vr = false; 10.40 + vr_module = 0; 10.41 + stereo = false; 10.42 +}
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/src/gameopt.h Sun Aug 24 09:41:24 2014 +0300 11.3 @@ -0,0 +1,16 @@ 11.4 +#ifndef GAMEOPT_H_ 11.5 +#define GAMEOPT_H_ 11.6 + 11.7 +struct GameOption { 11.8 + bool vr; 11.9 + char *vr_module; 11.10 + bool stereo; 11.11 + 11.12 + GameOption(); 11.13 +}; 11.14 + 11.15 +extern GameOption opt; 11.16 + 11.17 +bool parse_args(int argc, char **argv); 11.18 + 11.19 +#endif // GAMEOPT_H_
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/src/geom.cc Sun Aug 24 09:41:24 2014 +0300 12.3 @@ -0,0 +1,270 @@ 12.4 +#include <algorithm> 12.5 +#include <float.h> 12.6 +#include "geom.h" 12.7 +#include "logger.h" 12.8 + 12.9 +GeomObject::~GeomObject() 12.10 +{ 12.11 +} 12.12 + 12.13 + 12.14 +Sphere::Sphere() 12.15 +{ 12.16 + radius = 1.0; 12.17 +} 12.18 + 12.19 +Sphere::Sphere(const Vector3 ¢, float radius) 12.20 + : center(cent) 12.21 +{ 12.22 + this->radius = radius; 12.23 +} 12.24 + 12.25 +void Sphere::set_union(const GeomObject *obj1, const GeomObject *obj2) 12.26 +{ 12.27 + const Sphere *sph1 = dynamic_cast<const Sphere*>(obj1); 12.28 + const Sphere *sph2 = dynamic_cast<const Sphere*>(obj2); 12.29 + 12.30 + if(!sph1 || !sph2) { 12.31 + error_log("Sphere::set_union: arguments must be spheres"); 12.32 + return; 12.33 + } 12.34 + 12.35 + float dist = (sph1->center - sph2->center).length(); 12.36 + float surf_dist = dist - (sph1->radius + sph2->radius); 12.37 + float d1 = sph1->radius + surf_dist / 2.0; 12.38 + float d2 = sph2->radius + surf_dist / 2.0; 12.39 + float t = d1 / (d1 + d2); 12.40 + 12.41 + if(t < 0.0) t = 0.0; 12.42 + if(t > 1.0) t = 1.0; 12.43 + 12.44 + center = sph1->center * t + sph2->center * (1.0 - t); 12.45 + radius = std::max(dist * t + sph2->radius, dist * (1.0f - t) + sph1->radius); 12.46 +} 12.47 + 12.48 +void Sphere::set_intersection(const GeomObject *obj1, const GeomObject *obj2) 12.49 +{ 12.50 + error_log("Sphere::intersection undefined\n"); 12.51 +} 12.52 + 12.53 +bool Sphere::contains(const Vector3 &pt) const 12.54 +{ 12.55 + float dist_sq = (pt - center).length_sq(); 12.56 + return dist_sq <= radius * radius; 12.57 +} 12.58 + 12.59 +bool Sphere::intersect(const Ray &ray, HitPoint *hit) const 12.60 +{ 12.61 + float a = dot_product(ray.dir, ray.dir); 12.62 + float b = 2.0 * ray.dir.x * (ray.origin.x - center.x) + 12.63 + 2.0 * ray.dir.y * (ray.origin.y - center.y) + 12.64 + 2.0 * ray.dir.z * (ray.origin.z - center.z); 12.65 + float c = dot_product(ray.origin, ray.origin) + dot_product(center, center) - 12.66 + 2.0 * dot_product(ray.origin, center) - radius * radius; 12.67 + 12.68 + float discr = b * b - 4.0 * a * c; 12.69 + if(discr < 1e-4) { 12.70 + return false; 12.71 + } 12.72 + 12.73 + float sqrt_discr = sqrt(discr); 12.74 + float t0 = (-b + sqrt_discr) / (2.0 * a); 12.75 + float t1 = (-b - sqrt_discr) / (2.0 * a); 12.76 + 12.77 + if(t0 < 1e-4) 12.78 + t0 = t1; 12.79 + if(t1 < 1e-4) 12.80 + t1 = t0; 12.81 + 12.82 + float t = t0 < t1 ? t0 : t1; 12.83 + if(t < 1e-4) { 12.84 + return false; 12.85 + } 12.86 + 12.87 + // fill the HitPoint structure 12.88 + if(hit) { 12.89 + hit->obj = this; 12.90 + hit->dist = t; 12.91 + hit->pos = ray.origin + ray.dir * t; 12.92 + hit->normal = (hit->pos - center) / radius; 12.93 + } 12.94 + return true; 12.95 +} 12.96 + 12.97 + 12.98 +AABox::AABox() 12.99 +{ 12.100 +} 12.101 + 12.102 +AABox::AABox(const Vector3 &vmin, const Vector3 &vmax) 12.103 + : min(vmin), max(vmax) 12.104 +{ 12.105 +} 12.106 + 12.107 +void AABox::set_union(const GeomObject *obj1, const GeomObject *obj2) 12.108 +{ 12.109 + const AABox *box1 = dynamic_cast<const AABox*>(obj1); 12.110 + const AABox *box2 = dynamic_cast<const AABox*>(obj2); 12.111 + 12.112 + if(!box1 || !box2) { 12.113 + error_log("AABox::set_union: arguments must be AABoxes too\n"); 12.114 + return; 12.115 + } 12.116 + 12.117 + min.x = std::min(box1->min.x, box2->min.x); 12.118 + min.y = std::min(box1->min.y, box2->min.y); 12.119 + min.z = std::min(box1->min.z, box2->min.z); 12.120 + 12.121 + max.x = std::max(box1->max.x, box2->max.x); 12.122 + max.y = std::max(box1->max.y, box2->max.y); 12.123 + max.z = std::max(box1->max.z, box2->max.z); 12.124 +} 12.125 + 12.126 +void AABox::set_intersection(const GeomObject *obj1, const GeomObject *obj2) 12.127 +{ 12.128 + const AABox *box1 = dynamic_cast<const AABox*>(obj1); 12.129 + const AABox *box2 = dynamic_cast<const AABox*>(obj2); 12.130 + 12.131 + if(!box1 || !box2) { 12.132 + error_log("AABox::set_intersection: arguments must be AABoxes too\n"); 12.133 + return; 12.134 + } 12.135 + 12.136 + for(int i=0; i<3; i++) { 12.137 + min[i] = std::max(box1->min[i], box2->min[i]); 12.138 + max[i] = std::min(box1->max[i], box2->max[i]); 12.139 + 12.140 + if(max[i] < min[i]) { 12.141 + max[i] = min[i]; 12.142 + } 12.143 + } 12.144 +} 12.145 + 12.146 +bool AABox::contains(const Vector3 &pt) const 12.147 +{ 12.148 + return pt.x >= min.x && pt.x <= max.x && 12.149 + pt.y >= min.y && pt.y <= max.y && 12.150 + pt.z >= min.z && pt.z <= max.z; 12.151 +} 12.152 + 12.153 +bool AABox::intersect(const Ray &ray, HitPoint *hit) const 12.154 +{ 12.155 + Vector3 param[2] = {min, max}; 12.156 + Vector3 inv_dir(1.0 / ray.dir.x, 1.0 / ray.dir.y, 1.0 / ray.dir.z); 12.157 + int sign[3] = {inv_dir.x < 0, inv_dir.y < 0, inv_dir.z < 0}; 12.158 + 12.159 + float tmin = (param[sign[0]].x - ray.origin.x) * inv_dir.x; 12.160 + float tmax = (param[1 - sign[0]].x - ray.origin.x) * inv_dir.x; 12.161 + float tymin = (param[sign[1]].y - ray.origin.y) * inv_dir.y; 12.162 + float tymax = (param[1 - sign[1]].y - ray.origin.y) * inv_dir.y; 12.163 + 12.164 + if(tmin > tymax || tymin > tmax) { 12.165 + return false; 12.166 + } 12.167 + if(tymin > tmin) { 12.168 + tmin = tymin; 12.169 + } 12.170 + if(tymax < tmax) { 12.171 + tmax = tymax; 12.172 + } 12.173 + 12.174 + float tzmin = (param[sign[2]].z - ray.origin.z) * inv_dir.z; 12.175 + float tzmax = (param[1 - sign[2]].z - ray.origin.z) * inv_dir.z; 12.176 + 12.177 + if(tmin > tzmax || tzmin > tmax) { 12.178 + return false; 12.179 + } 12.180 + if(tzmin > tmin) { 12.181 + tmin = tzmin; 12.182 + } 12.183 + if(tzmax < tmax) { 12.184 + tmax = tzmax; 12.185 + } 12.186 + 12.187 + float t = tmin < 1e-4 ? tmax : tmin; 12.188 + if(t >= 1e-4) { 12.189 + 12.190 + if(hit) { 12.191 + hit->obj = this; 12.192 + hit->dist = t; 12.193 + hit->pos = ray.origin + ray.dir * t; 12.194 + 12.195 + float min_dist = FLT_MAX; 12.196 + Vector3 offs = min + (max - min) / 2.0; 12.197 + Vector3 local_hit = hit->pos - offs; 12.198 + 12.199 + static const Vector3 axis[] = { 12.200 + Vector3(1, 0, 0), Vector3(0, 1, 0), Vector3(0, 0, 1) 12.201 + }; 12.202 + //int tcidx[][2] = {{2, 1}, {0, 2}, {0, 1}}; 12.203 + 12.204 + for(int i=0; i<3; i++) { 12.205 + float dist = fabs((max[i] - offs[i]) - fabs(local_hit[i])); 12.206 + if(dist < min_dist) { 12.207 + min_dist = dist; 12.208 + hit->normal = axis[i] * (local_hit[i] < 0.0 ? 1.0 : -1.0); 12.209 + //hit->texcoord = Vector2(hit->pos[tcidx[i][0]], hit->pos[tcidx[i][1]]); 12.210 + } 12.211 + } 12.212 + } 12.213 + return true; 12.214 + } 12.215 + return false; 12.216 + 12.217 +} 12.218 + 12.219 +Plane::Plane() 12.220 + : normal(0.0, 1.0, 0.0) 12.221 +{ 12.222 +} 12.223 + 12.224 +Plane::Plane(const Vector3 &p, const Vector3 &norm) 12.225 + : pt(p) 12.226 +{ 12.227 + normal = norm.normalized(); 12.228 +} 12.229 + 12.230 +Plane::Plane(const Vector3 &p1, const Vector3 &p2, const Vector3 &p3) 12.231 + : pt(p1) 12.232 +{ 12.233 + normal = cross_product(p2 - p1, p3 - p1).normalized(); 12.234 +} 12.235 + 12.236 +Plane::Plane(const Vector3 &normal, float dist) 12.237 +{ 12.238 + this->normal = normal.normalized(); 12.239 + pt = this->normal * dist; 12.240 +} 12.241 + 12.242 +void Plane::set_union(const GeomObject *obj1, const GeomObject *obj2) 12.243 +{ 12.244 + error_log("Plane::set_union undefined\n"); 12.245 +} 12.246 + 12.247 +void Plane::set_intersection(const GeomObject *obj1, const GeomObject *obj2) 12.248 +{ 12.249 + error_log("Plane::set_intersection undefined\n"); 12.250 +} 12.251 + 12.252 +bool Plane::contains(const Vector3 &pt) const 12.253 +{ 12.254 + return false; // TODO: maybe define containment as half-space containment? 12.255 +} 12.256 + 12.257 +bool Plane::intersect(const Ray &ray, HitPoint *hit) const 12.258 +{ 12.259 + float ndotdir = dot_product(normal, ray.dir); 12.260 + if(fabs(ndotdir) < 1e-4) { 12.261 + return false; 12.262 + } 12.263 + 12.264 + if(hit) { 12.265 + Vector3 ptdir = pt - ray.origin; 12.266 + float t = dot_product(normal, ptdir) / ndotdir; 12.267 + 12.268 + hit->pos = ray.origin + ray.dir * t; 12.269 + hit->normal = normal; 12.270 + hit->obj = this; 12.271 + } 12.272 + return true; 12.273 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/src/geom.h Sun Aug 24 09:41:24 2014 +0300 13.3 @@ -0,0 +1,71 @@ 13.4 +#ifndef GEOMOBJ_H_ 13.5 +#define GEOMOBJ_H_ 13.6 + 13.7 +#include "vmath/vmath.h" 13.8 + 13.9 +class GeomObject; 13.10 + 13.11 +struct HitPoint { 13.12 + float dist; //< parametric distance along the ray 13.13 + Vector3 pos; //< position of intersection (orig + dir * dist) 13.14 + Vector3 normal; //< normal at the point of intersection 13.15 + const void *obj; //< pointer to the intersected object 13.16 +}; 13.17 + 13.18 +class GeomObject { 13.19 +public: 13.20 + virtual ~GeomObject(); 13.21 + 13.22 + virtual void set_union(const GeomObject *obj1, const GeomObject *obj2) = 0; 13.23 + virtual void set_intersection(const GeomObject *obj1, const GeomObject *obj2) = 0; 13.24 + 13.25 + virtual bool contains(const Vector3 &pt) const = 0; 13.26 + virtual bool intersect(const Ray &ray, HitPoint *hit = 0) const = 0; 13.27 +}; 13.28 + 13.29 +class Sphere : public GeomObject { 13.30 +public: 13.31 + Vector3 center; 13.32 + float radius; 13.33 + 13.34 + Sphere(); 13.35 + Sphere(const Vector3 ¢er, float radius); 13.36 + 13.37 + void set_union(const GeomObject *obj1, const GeomObject *obj2); 13.38 + void set_intersection(const GeomObject *obj1, const GeomObject *obj2); 13.39 + 13.40 + bool contains(const Vector3 &pt) const; 13.41 + bool intersect(const Ray &ray, HitPoint *hit = 0) const; 13.42 +}; 13.43 + 13.44 +class AABox : public GeomObject { 13.45 +public: 13.46 + Vector3 min, max; 13.47 + 13.48 + AABox(); 13.49 + AABox(const Vector3 &min, const Vector3 &max); 13.50 + 13.51 + void set_union(const GeomObject *obj1, const GeomObject *obj2); 13.52 + void set_intersection(const GeomObject *obj1, const GeomObject *obj2); 13.53 + 13.54 + bool contains(const Vector3 &pt) const; 13.55 + bool intersect(const Ray &ray, HitPoint *hit = 0) const; 13.56 +}; 13.57 + 13.58 +class Plane : public GeomObject { 13.59 +public: 13.60 + Vector3 pt, normal; 13.61 + 13.62 + Plane(); 13.63 + Plane(const Vector3 &pt, const Vector3 &normal); 13.64 + Plane(const Vector3 &p1, const Vector3 &p2, const Vector3 &p3); 13.65 + Plane(const Vector3 &normal, float dist); 13.66 + 13.67 + void set_union(const GeomObject *obj1, const GeomObject *obj2); 13.68 + void set_intersection(const GeomObject *obj1, const GeomObject *obj2); 13.69 + 13.70 + bool contains(const Vector3 &pt) const; 13.71 + bool intersect(const Ray &ray, HitPoint *hit = 0) const; 13.72 +}; 13.73 + 13.74 +#endif // GEOMOBJ_H_
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/src/light.cc Sun Aug 24 09:41:24 2014 +0300 14.3 @@ -0,0 +1,36 @@ 14.4 +#include "light.h" 14.5 + 14.6 +Light::Light() 14.7 +{ 14.8 + cast_shadows = false; 14.9 +} 14.10 + 14.11 +void Light::set_color(const Vector3 &color) 14.12 +{ 14.13 + this->color = color; 14.14 +} 14.15 + 14.16 +const Vector3 &Light::get_color() const 14.17 +{ 14.18 + return color; 14.19 +} 14.20 + 14.21 +void Light::set_attenuation(const Vector3 &att) 14.22 +{ 14.23 + attenuation = att; 14.24 +} 14.25 + 14.26 +const Vector3 &Light::get_attenuation() const 14.27 +{ 14.28 + return attenuation; 14.29 +} 14.30 + 14.31 +void Light::set_shadow_caster(bool s) 14.32 +{ 14.33 + cast_shadows = s; 14.34 +} 14.35 + 14.36 +bool Light::is_shadow_caster() const 14.37 +{ 14.38 + return cast_shadows; 14.39 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/src/light.h Sun Aug 24 09:41:24 2014 +0300 15.3 @@ -0,0 +1,27 @@ 15.4 +#ifndef GOATGFX_LIGHT_H_ 15.5 +#define GOATGFX_LIGHT_H_ 15.6 + 15.7 +#include "xform_node.h" 15.8 + 15.9 + 15.10 +class Light : public XFormNode { 15.11 +private: 15.12 + Vector3 color; 15.13 + Vector3 attenuation; 15.14 + 15.15 + bool cast_shadows; 15.16 + 15.17 +public: 15.18 + Light(); 15.19 + 15.20 + void set_color(const Vector3 &color); 15.21 + const Vector3 &get_color() const; 15.22 + 15.23 + void set_attenuation(const Vector3 &att); 15.24 + const Vector3 &get_attenuation() const; 15.25 + 15.26 + void set_shadow_caster(bool s); 15.27 + bool is_shadow_caster() const; 15.28 +}; 15.29 + 15.30 +#endif // GOATGFX_LIGHT_H_
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/src/logger.cc Sun Aug 24 09:41:24 2014 +0300 16.3 @@ -0,0 +1,118 @@ 16.4 +#include <stdio.h> 16.5 +#include <stdarg.h> 16.6 +#include "logger.h" 16.7 + 16.8 +#if defined(unix) || defined(__unix__) || defined(__APPLE__) 16.9 +#include <unistd.h> 16.10 +#elif defined(WIN32) 16.11 +#include <windows.h> 16.12 +#endif 16.13 + 16.14 +enum { LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_FATAL, LOG_DEBUG }; 16.15 + 16.16 +static int typecolor(int type); 16.17 + 16.18 +static FILE *fp = stdout; 16.19 + 16.20 +static void logmsg(int type, const char *fmt, va_list ap) 16.21 +{ 16.22 +#if defined(unix) || defined(__unix__) || (defined(__APPLE__) && !defined(TARGET_IPHONE)) 16.23 + if(isatty(fileno(fp)) && type != LOG_INFO) { 16.24 + int c = typecolor(type); 16.25 + fprintf(fp, "\033[%dm", c); 16.26 + vfprintf(fp, fmt, ap); 16.27 + fprintf(fp, "\033[0m"); 16.28 + } else 16.29 +#endif 16.30 + { 16.31 + vfprintf(fp, fmt, ap); 16.32 + } 16.33 + if(type == LOG_ERROR || type == LOG_FATAL || type == LOG_DEBUG) { 16.34 + fflush(fp); 16.35 + } 16.36 + 16.37 +#ifdef WIN32 16.38 + if(type == LOG_FATAL) { 16.39 + static char msgbuf[1024]; 16.40 + vsnprintf(msgbuf, sizeof msgbuf - 1, fmt, ap); 16.41 + msgbuf[sizeof msgbuf - 1] = 0; 16.42 + MessageBox(0, msgbuf, "Fatal error", MB_OK | MB_ICONSTOP); 16.43 + } 16.44 +#endif 16.45 +} 16.46 + 16.47 +void info_log(const char *fmt, ...) 16.48 +{ 16.49 + va_list ap; 16.50 + 16.51 + va_start(ap, fmt); 16.52 + logmsg(LOG_INFO, fmt, ap); 16.53 + va_end(ap); 16.54 +} 16.55 + 16.56 +void warning_log(const char *fmt, ...) 16.57 +{ 16.58 + va_list ap; 16.59 + 16.60 + va_start(ap, fmt); 16.61 + logmsg(LOG_WARNING, fmt, ap); 16.62 + va_end(ap); 16.63 +} 16.64 + 16.65 +void error_log(const char *fmt, ...) 16.66 +{ 16.67 + va_list ap; 16.68 + 16.69 + va_start(ap, fmt); 16.70 + logmsg(LOG_ERROR, fmt, ap); 16.71 + va_end(ap); 16.72 +} 16.73 + 16.74 +void fatal_log(const char *fmt, ...) 16.75 +{ 16.76 + va_list ap; 16.77 + 16.78 + va_start(ap, fmt); 16.79 + logmsg(LOG_FATAL, fmt, ap); 16.80 + va_end(ap); 16.81 +} 16.82 + 16.83 +void debug_log(const char *fmt, ...) 16.84 +{ 16.85 + va_list ap; 16.86 + 16.87 + va_start(ap, fmt); 16.88 + logmsg(LOG_DEBUG, fmt, ap); 16.89 + va_end(ap); 16.90 +} 16.91 + 16.92 +enum { 16.93 + BLACK = 0, 16.94 + RED, 16.95 + GREEN, 16.96 + YELLOW, 16.97 + BLUE, 16.98 + MAGENTA, 16.99 + CYAN, 16.100 + WHITE 16.101 +}; 16.102 + 16.103 +#define ANSI_FGCOLOR(x) (30 + (x)) 16.104 +#define ANSI_BGCOLOR(x) (40 + (x)) 16.105 + 16.106 +static int typecolor(int type) 16.107 +{ 16.108 + switch(type) { 16.109 + case LOG_ERROR: 16.110 + return ANSI_FGCOLOR(RED); 16.111 + case LOG_FATAL: 16.112 + return ANSI_FGCOLOR(RED); // TODO differentiate from LOG_ERROR 16.113 + case LOG_WARNING: 16.114 + return ANSI_FGCOLOR(YELLOW); 16.115 + case LOG_DEBUG: 16.116 + return ANSI_FGCOLOR(MAGENTA); 16.117 + default: 16.118 + break; 16.119 + } 16.120 + return 37; 16.121 +}
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/src/logger.h Sun Aug 24 09:41:24 2014 +0300 17.3 @@ -0,0 +1,10 @@ 17.4 +#ifndef LOGGER_H_ 17.5 +#define LOGGER_H_ 17.6 + 17.7 +void info_log(const char *fmt, ...); 17.8 +void warning_log(const char *fmt, ...); 17.9 +void error_log(const char *fmt, ...); 17.10 +void fatal_log(const char *fmt, ...); 17.11 +void debug_log(const char *fmt, ...); 17.12 + 17.13 +#endif // LOGGER_H_
18.1 --- a/src/main.cc Sat Aug 23 12:03:29 2014 +0300 18.2 +++ b/src/main.cc Sun Aug 24 09:41:24 2014 +0300 18.3 @@ -2,6 +2,7 @@ 18.4 #include <stdlib.h> 18.5 #include "opengl.h" 18.6 #include "game.h" 18.7 +#include "gameopt.h" 18.8 #include "vr/vr.h" 18.9 18.10 static bool init(); 18.11 @@ -23,8 +24,13 @@ 18.12 { 18.13 glutInitWindowSize(1024, 600); 18.14 glutInit(&argc, argv); 18.15 - glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); 18.16 - glutCreateWindow("VR Chess"); 18.17 + 18.18 + if(!parse_args(argc, argv)) { 18.19 + return 1; 18.20 + } 18.21 + 18.22 + glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | (opt.stereo ? GLUT_STEREO : 0)); 18.23 + glutCreateWindow("LD48 #30 - connected worlds"); 18.24 18.25 glutDisplayFunc(display); 18.26 glutIdleFunc(idle); 18.27 @@ -53,10 +59,12 @@ 18.28 return false; 18.29 } 18.30 18.31 - int win_xsz = vr_get_opti(VR_OPT_DISPLAY_WIDTH); 18.32 - int win_ysz = vr_get_opti(VR_OPT_DISPLAY_HEIGHT); 18.33 - if(win_xsz && win_ysz) { 18.34 - glutReshapeWindow(win_xsz, win_ysz); 18.35 + if(opt.vr) { 18.36 + int win_xsz = vr_get_opti(VR_OPT_DISPLAY_WIDTH); 18.37 + int win_ysz = vr_get_opti(VR_OPT_DISPLAY_HEIGHT); 18.38 + if(win_xsz && win_ysz) { 18.39 + glutReshapeWindow(win_xsz, win_ysz); 18.40 + } 18.41 } 18.42 return true; 18.43 } 18.44 @@ -110,8 +118,8 @@ 18.45 if(xoffs || yoffs) { 18.46 printf("repositioning: %d,%d\n", xoffs, yoffs); 18.47 glutPositionWindow(xoffs, yoffs); 18.48 - fullscreen_pending = true; 18.49 } 18.50 + fullscreen_pending = true; 18.51 } else { 18.52 fullscreen_pending = false; 18.53 glutPositionWindow(prev_xpos, prev_ypos);
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 19.2 +++ b/src/material.cc Sun Aug 24 09:41:24 2014 +0300 19.3 @@ -0,0 +1,75 @@ 19.4 +#include "opengl.h" 19.5 +#include "material.h" 19.6 +#include "unistate.h" 19.7 + 19.8 +Material::Material() 19.9 + : diffuse(1, 1, 1), specular(0, 0, 0) 19.10 +{ 19.11 + alpha = 1.0; 19.12 + shininess = 1.0; 19.13 + 19.14 + for(int i=0; i<MAX_MTL_TEXTURES; i++) { 19.15 + tex[i] = 0; 19.16 + } 19.17 +} 19.18 + 19.19 + 19.20 +void Material::setup(bool use_textures) const 19.21 +{ 19.22 + static bool done_init; 19.23 + static int st_diffuse_idx, st_specular_idx, st_shininess_idx, st_alpha_idx; 19.24 + static int st_tex_diffuse_idx, st_tex_specular_idx, st_tex_normal_idx; 19.25 + static int st_tex_idx[MAX_MTL_TEXTURES]; 19.26 + 19.27 + if(!done_init) { 19.28 + st_diffuse_idx = add_unistate("st_mtl_diffuse", ST_FLOAT3); 19.29 + st_specular_idx = add_unistate("st_mtl_specular", ST_FLOAT3); 19.30 + st_shininess_idx = add_unistate("st_mtl_shininess", ST_FLOAT); 19.31 + st_alpha_idx = add_unistate("st_mtl_alpha", ST_FLOAT); 19.32 + st_tex_diffuse_idx = add_unistate("st_tex_diffuse", ST_INT); 19.33 + st_tex_specular_idx = add_unistate("st_tex_specular", ST_INT); 19.34 + st_tex_normal_idx = add_unistate("st_tex_normal", ST_INT); 19.35 + 19.36 + for(int i=0; i<MAX_MTL_TEXTURES; i++) { 19.37 + char name[32]; 19.38 + sprintf(name, "st_tex%d", i); 19.39 + st_tex_idx[i] = add_unistate(name, ST_INT); 19.40 + } 19.41 + done_init = true; 19.42 + } 19.43 + 19.44 + set_unistate(st_diffuse_idx, diffuse); 19.45 + set_unistate(st_specular_idx, specular); 19.46 + set_unistate(st_shininess_idx, shininess); 19.47 + set_unistate(st_alpha_idx, alpha); 19.48 + 19.49 + if(!use_textures) { 19.50 + return; // we're done 19.51 + } 19.52 + 19.53 + const int tex_named_idx[] = { 19.54 + st_tex_diffuse_idx, st_tex_specular_idx, st_tex_normal_idx, -1 19.55 + }; 19.56 + 19.57 + int tex_unit = 0; 19.58 + for(int i=0; i<MAX_MTL_TEXTURES; i++) { 19.59 + if(tex[i]) { 19.60 + bind_texture(tex[i], tex_unit); 19.61 + 19.62 + if(tex_named_idx[i] != -1) { 19.63 + set_unistate(tex_named_idx[i], tex_unit); 19.64 + } 19.65 + set_unistate(st_tex_idx[i], tex_unit); 19.66 + tex_unit++; 19.67 + } 19.68 + } 19.69 + 19.70 + // also do fixed-function setup 19.71 + float dcol[] = {diffuse.x, diffuse.y, diffuse.z, alpha}; 19.72 + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, dcol); 19.73 + 19.74 + float scol[] = {specular.x, specular.y, specular.z, 1.0f}; 19.75 + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, scol); 19.76 + 19.77 + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess); 19.78 +}
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 20.2 +++ b/src/material.h Sun Aug 24 09:41:24 2014 +0300 20.3 @@ -0,0 +1,29 @@ 20.4 +#ifndef MATERIAL_H_ 20.5 +#define MATERIAL_H_ 20.6 + 20.7 +#include "vmath/vmath.h" 20.8 +#include "texture.h" 20.9 + 20.10 +enum { 20.11 + TEX_DIFFUSE, 20.12 + TEX_SPECULAR, 20.13 + TEX_NORMAL, 20.14 + TEX_MISC, 20.15 + 20.16 + MAX_MTL_TEXTURES 20.17 +}; 20.18 + 20.19 +class Material { 20.20 +public: 20.21 + Vector3 diffuse, specular; 20.22 + float alpha; 20.23 + float shininess; 20.24 + 20.25 + Texture *tex[MAX_MTL_TEXTURES]; 20.26 + 20.27 + Material(); 20.28 + 20.29 + void setup(bool use_textures = true) const; 20.30 +}; 20.31 + 20.32 +#endif // MATERIAL_H_
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/src/mesh.cc Sun Aug 24 09:41:24 2014 +0300 21.3 @@ -0,0 +1,1024 @@ 21.4 +#include <stdio.h> 21.5 +#include <stdlib.h> 21.6 +#include <float.h> 21.7 +#include <assert.h> 21.8 +#include "opengl.h" 21.9 +#include "mesh.h" 21.10 +#include "xform_node.h" 21.11 +#include "shader.h" 21.12 +#include "logger.h" 21.13 + 21.14 +int Mesh::global_sdr_loc[NUM_MESH_ATTR] = { 0, 1, 2, 3, 4, 5 }; 21.15 +unsigned int Mesh::intersect_mode = ISECT_DEFAULT; 21.16 +float Mesh::vertex_sel_dist = 0.01; 21.17 +float Mesh::vis_vecsize = 1.0; 21.18 + 21.19 +Mesh::Mesh() 21.20 +{ 21.21 + clear(); 21.22 + 21.23 + glGenBuffers(NUM_MESH_ATTR + 1, buffer_objects); 21.24 + 21.25 + for(int i=0; i<NUM_MESH_ATTR; i++) { 21.26 + vattr[i].vbo = buffer_objects[i]; 21.27 + } 21.28 + ibo = buffer_objects[NUM_MESH_ATTR]; 21.29 + wire_ibo = 0; 21.30 +} 21.31 + 21.32 +Mesh::~Mesh() 21.33 +{ 21.34 + glDeleteBuffers(NUM_MESH_ATTR + 1, buffer_objects); 21.35 + 21.36 + if(wire_ibo) { 21.37 + glDeleteBuffers(1, &wire_ibo); 21.38 + } 21.39 +} 21.40 + 21.41 +void Mesh::set_name(const char *name) 21.42 +{ 21.43 + this->name = name; 21.44 +} 21.45 + 21.46 +const char *Mesh::get_name() const 21.47 +{ 21.48 + return name.c_str(); 21.49 +} 21.50 + 21.51 +bool Mesh::has_attrib(int attr) const 21.52 +{ 21.53 + if(attr < 0 || attr >= NUM_MESH_ATTR) { 21.54 + return false; 21.55 + } 21.56 + 21.57 + // if neither of these is valid, then nobody has set this attribute 21.58 + return vattr[attr].vbo_valid || vattr[attr].data_valid; 21.59 +} 21.60 + 21.61 +void Mesh::clear() 21.62 +{ 21.63 + bones.clear(); 21.64 + 21.65 + for(int i=0; i<NUM_MESH_ATTR; i++) { 21.66 + vattr[i].nelem = 0; 21.67 + vattr[i].vbo_valid = false; 21.68 + vattr[i].data_valid = false; 21.69 + //vattr[i].sdr_loc = -1; 21.70 + vattr[i].data.clear(); 21.71 + } 21.72 + ibo_valid = idata_valid = false; 21.73 + idata.clear(); 21.74 + 21.75 + wire_ibo_valid = false; 21.76 + 21.77 + nverts = nfaces = 0; 21.78 + 21.79 + bsph_valid = false; 21.80 + aabb_valid = false; 21.81 +} 21.82 + 21.83 +float *Mesh::set_attrib_data(int attrib, int nelem, unsigned int num, const float *data) 21.84 +{ 21.85 + if(attrib < 0 || attrib >= NUM_MESH_ATTR) { 21.86 + error_log("%s: invalid attrib: %d\n", __FUNCTION__, attrib); 21.87 + return 0; 21.88 + } 21.89 + 21.90 + if(nverts && num != nverts) { 21.91 + error_log("%s: attribute count missmatch (%d instead of %d)\n", __FUNCTION__, num, nverts); 21.92 + return 0; 21.93 + } 21.94 + nverts = num; 21.95 + 21.96 + vattr[attrib].data.clear(); 21.97 + vattr[attrib].nelem = nelem; 21.98 + vattr[attrib].data.resize(num * nelem); 21.99 + 21.100 + if(data) { 21.101 + memcpy(&vattr[attrib].data[0], data, num * nelem * sizeof *data); 21.102 + } 21.103 + 21.104 + vattr[attrib].data_valid = true; 21.105 + vattr[attrib].vbo_valid = false; 21.106 + return &vattr[attrib].data[0]; 21.107 +} 21.108 + 21.109 +float *Mesh::get_attrib_data(int attrib) 21.110 +{ 21.111 + if(attrib < 0 || attrib >= NUM_MESH_ATTR) { 21.112 + error_log("%s: invalid attrib: %d\n", __FUNCTION__, attrib); 21.113 + return 0; 21.114 + } 21.115 + 21.116 + vattr[attrib].vbo_valid = false; 21.117 + return (float*)((const Mesh*)this)->get_attrib_data(attrib); 21.118 +} 21.119 + 21.120 +const float *Mesh::get_attrib_data(int attrib) const 21.121 +{ 21.122 + if(attrib < 0 || attrib >= NUM_MESH_ATTR) { 21.123 + error_log("%s: invalid attrib: %d\n", __FUNCTION__, attrib); 21.124 + return 0; 21.125 + } 21.126 + 21.127 + if(!vattr[attrib].data_valid) { 21.128 +#if GL_ES_VERSION_2_0 21.129 + error_log("%s: can't read back attrib data on CrippledGL ES\n", __FUNCTION__); 21.130 + return 0; 21.131 +#else 21.132 + if(!vattr[attrib].vbo_valid) { 21.133 + error_log("%s: unavailable attrib: %d\n", __FUNCTION__, attrib); 21.134 + return 0; 21.135 + } 21.136 + 21.137 + // local data copy is unavailable, grab the data from the vbo 21.138 + Mesh *m = (Mesh*)this; 21.139 + m->vattr[attrib].data.resize(nverts * vattr[attrib].nelem); 21.140 + 21.141 + glBindBuffer(GL_ARRAY_BUFFER, vattr[attrib].vbo); 21.142 + void *data = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY); 21.143 + memcpy(&m->vattr[attrib].data[0], data, nverts * vattr[attrib].nelem * sizeof(float)); 21.144 + glUnmapBuffer(GL_ARRAY_BUFFER); 21.145 + 21.146 + vattr[attrib].data_valid = true; 21.147 +#endif 21.148 + } 21.149 + 21.150 + return &vattr[attrib].data[0]; 21.151 +} 21.152 + 21.153 +void Mesh::set_attrib(int attrib, int idx, const Vector4 &v) 21.154 +{ 21.155 + float *data = get_attrib_data(attrib); 21.156 + if(data) { 21.157 + data += idx * vattr[attrib].nelem; 21.158 + for(int i=0; i<vattr[attrib].nelem; i++) { 21.159 + data[i] = v[i]; 21.160 + } 21.161 + } 21.162 +} 21.163 + 21.164 +Vector4 Mesh::get_attrib(int attrib, int idx) const 21.165 +{ 21.166 + Vector4 v(0.0, 0.0, 0.0, 1.0); 21.167 + const float *data = get_attrib_data(attrib); 21.168 + if(data) { 21.169 + data += idx * vattr[attrib].nelem; 21.170 + for(int i=0; i<vattr[attrib].nelem; i++) { 21.171 + v[i] = data[i]; 21.172 + } 21.173 + } 21.174 + return v; 21.175 +} 21.176 + 21.177 +unsigned int *Mesh::set_index_data(int num, const unsigned int *indices) 21.178 +{ 21.179 + int nidx = nfaces * 3; 21.180 + if(nidx && num != nidx) { 21.181 + error_log("%s: index count missmatch (%d instead of %d)\n", __FUNCTION__, num, nidx); 21.182 + return 0; 21.183 + } 21.184 + nfaces = num / 3; 21.185 + 21.186 + idata.clear(); 21.187 + idata.resize(num); 21.188 + 21.189 + if(indices) { 21.190 + memcpy(&idata[0], indices, num * sizeof *indices); 21.191 + } 21.192 + 21.193 + idata_valid = true; 21.194 + ibo_valid = false; 21.195 + 21.196 + return &idata[0]; 21.197 +} 21.198 + 21.199 +unsigned int *Mesh::get_index_data() 21.200 +{ 21.201 + ibo_valid = false; 21.202 + return (unsigned int*)((const Mesh*)this)->get_index_data(); 21.203 +} 21.204 + 21.205 +const unsigned int *Mesh::get_index_data() const 21.206 +{ 21.207 + if(!idata_valid) { 21.208 +#if GL_ES_VERSION_2_0 21.209 + error_log("%s: can't read back index data in CrippledGL ES\n", __FUNCTION__); 21.210 + return 0; 21.211 +#else 21.212 + if(!ibo_valid) { 21.213 + error_log("%s: indices unavailable\n", __FUNCTION__); 21.214 + return 0; 21.215 + } 21.216 + 21.217 + // local data copy is unavailable, gram the data from the ibo 21.218 + Mesh *m = (Mesh*)this; 21.219 + int nidx = nfaces * 3; 21.220 + m->idata.resize(nidx); 21.221 + 21.222 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 21.223 + void *data = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY); 21.224 + memcpy(&m->idata[0], data, nidx * sizeof(unsigned int)); 21.225 + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); 21.226 + 21.227 + idata_valid = true; 21.228 +#endif 21.229 + } 21.230 + 21.231 + return &idata[0]; 21.232 +} 21.233 + 21.234 +void Mesh::append(const Mesh &mesh) 21.235 +{ 21.236 + unsigned int idxoffs = nverts; 21.237 + 21.238 + nverts += mesh.nverts; 21.239 + nfaces += mesh.nfaces; 21.240 + 21.241 + for(int i=0; i<NUM_MESH_ATTR; i++) { 21.242 + if(has_attrib(i) && mesh.has_attrib(i)) { 21.243 + // force validating the data arrays 21.244 + get_attrib_data(i); 21.245 + mesh.get_attrib_data(i); 21.246 + 21.247 + // append the mesh data 21.248 + vattr[i].data.insert(vattr[i].data.end(), mesh.vattr[i].data.begin(), mesh.vattr[i].data.end()); 21.249 + } 21.250 + } 21.251 + 21.252 + if(ibo_valid || idata_valid) { 21.253 + // make index arrays valid 21.254 + get_index_data(); 21.255 + mesh.get_index_data(); 21.256 + 21.257 + size_t orig_sz = idata.size(); 21.258 + 21.259 + idata.insert(idata.end(), mesh.idata.begin(), mesh.idata.end()); 21.260 + 21.261 + // fixup all the new indices 21.262 + for(size_t i=orig_sz; i<idata.size(); i++) { 21.263 + idata[i] += idxoffs; 21.264 + } 21.265 + } 21.266 + 21.267 + // fuck everything 21.268 + wire_ibo_valid = false; 21.269 + aabb_valid = false; 21.270 + bsph_valid = false; 21.271 +} 21.272 + 21.273 +// assemble a complete vertex by adding all the useful attributes 21.274 +void Mesh::vertex(float x, float y, float z) 21.275 +{ 21.276 + cur_val[MESH_ATTR_VERTEX] = Vector4(x, y, z, 1.0f); 21.277 + vattr[MESH_ATTR_VERTEX].data_valid = true; 21.278 + vattr[MESH_ATTR_VERTEX].nelem = 3; 21.279 + 21.280 + for(int i=0; i<NUM_MESH_ATTR; i++) { 21.281 + if(vattr[i].data_valid) { 21.282 + for(int j=0; j<vattr[MESH_ATTR_VERTEX].nelem; j++) { 21.283 + vattr[i].data.push_back(cur_val[i][j]); 21.284 + } 21.285 + } 21.286 + vattr[i].vbo_valid = false; 21.287 + } 21.288 + 21.289 + if(idata_valid) { 21.290 + idata.clear(); 21.291 + } 21.292 + ibo_valid = idata_valid = false; 21.293 +} 21.294 + 21.295 +void Mesh::normal(float nx, float ny, float nz) 21.296 +{ 21.297 + cur_val[MESH_ATTR_NORMAL] = Vector4(nx, ny, nz, 1.0f); 21.298 + vattr[MESH_ATTR_NORMAL].data_valid = true; 21.299 + vattr[MESH_ATTR_NORMAL].nelem = 3; 21.300 +} 21.301 + 21.302 +void Mesh::tangent(float tx, float ty, float tz) 21.303 +{ 21.304 + cur_val[MESH_ATTR_TANGENT] = Vector4(tx, ty, tz, 1.0f); 21.305 + vattr[MESH_ATTR_TANGENT].data_valid = true; 21.306 + vattr[MESH_ATTR_TANGENT].nelem = 3; 21.307 +} 21.308 + 21.309 +void Mesh::texcoord(float u, float v, float w) 21.310 +{ 21.311 + cur_val[MESH_ATTR_TEXCOORD] = Vector4(u, v, w, 1.0f); 21.312 + vattr[MESH_ATTR_TEXCOORD].data_valid = true; 21.313 + vattr[MESH_ATTR_TEXCOORD].nelem = 3; 21.314 +} 21.315 + 21.316 +void Mesh::boneweights(float w1, float w2, float w3, float w4) 21.317 +{ 21.318 + cur_val[MESH_ATTR_BONEWEIGHTS] = Vector4(w1, w2, w3, w4); 21.319 + vattr[MESH_ATTR_BONEWEIGHTS].data_valid = true; 21.320 + vattr[MESH_ATTR_BONEWEIGHTS].nelem = 4; 21.321 +} 21.322 + 21.323 +void Mesh::boneidx(int idx1, int idx2, int idx3, int idx4) 21.324 +{ 21.325 + cur_val[MESH_ATTR_BONEIDX] = Vector4(idx1, idx2, idx3, idx4); 21.326 + vattr[MESH_ATTR_BONEIDX].data_valid = true; 21.327 + vattr[MESH_ATTR_BONEIDX].nelem = 4; 21.328 +} 21.329 + 21.330 +/// static function 21.331 +void Mesh::set_attrib_location(int attr, int loc) 21.332 +{ 21.333 + if(attr < 0 || attr >= NUM_MESH_ATTR) { 21.334 + return; 21.335 + } 21.336 + Mesh::global_sdr_loc[attr] = loc; 21.337 +} 21.338 + 21.339 +/// static function 21.340 +int Mesh::get_attrib_location(int attr) 21.341 +{ 21.342 + if(attr < 0 || attr >= NUM_MESH_ATTR) { 21.343 + return -1; 21.344 + } 21.345 + return Mesh::global_sdr_loc[attr]; 21.346 +} 21.347 + 21.348 +/// static function 21.349 +void Mesh::clear_attrib_locations() 21.350 +{ 21.351 + for(int i=0; i<NUM_MESH_ATTR; i++) { 21.352 + Mesh::global_sdr_loc[i] = -1; 21.353 + } 21.354 +} 21.355 + 21.356 +/// static function 21.357 +void Mesh::set_vis_vecsize(float sz) 21.358 +{ 21.359 + Mesh::vis_vecsize = sz; 21.360 +} 21.361 + 21.362 +float Mesh::get_vis_vecsize() 21.363 +{ 21.364 + return Mesh::vis_vecsize; 21.365 +} 21.366 + 21.367 +void Mesh::apply_xform(const Matrix4x4 &xform) 21.368 +{ 21.369 + Matrix4x4 dir_xform = xform; 21.370 + dir_xform[0][3] = dir_xform[1][3] = dir_xform[2][3] = 0.0f; 21.371 + dir_xform[3][0] = dir_xform[3][1] = dir_xform[3][2] = 0.0f; 21.372 + dir_xform[3][3] = 1.0f; 21.373 + 21.374 + apply_xform(xform, dir_xform); 21.375 +} 21.376 + 21.377 +void Mesh::apply_xform(const Matrix4x4 &xform, const Matrix4x4 &dir_xform) 21.378 +{ 21.379 + for(unsigned int i=0; i<nverts; i++) { 21.380 + Vector4 v = get_attrib(MESH_ATTR_VERTEX, i); 21.381 + set_attrib(MESH_ATTR_VERTEX, i, v.transformed(xform)); 21.382 + 21.383 + if(has_attrib(MESH_ATTR_NORMAL)) { 21.384 + Vector3 n = get_attrib(MESH_ATTR_NORMAL, i); 21.385 + set_attrib(MESH_ATTR_NORMAL, i, n.transformed(dir_xform)); 21.386 + } 21.387 + if(has_attrib(MESH_ATTR_TANGENT)) { 21.388 + Vector3 t = get_attrib(MESH_ATTR_TANGENT, i); 21.389 + set_attrib(MESH_ATTR_TANGENT, i, t.transformed(dir_xform)); 21.390 + } 21.391 + } 21.392 +} 21.393 + 21.394 +int Mesh::add_bone(XFormNode *bone) 21.395 +{ 21.396 + int idx = bones.size(); 21.397 + bones.push_back(bone); 21.398 + return idx; 21.399 +} 21.400 + 21.401 +const XFormNode *Mesh::get_bone(int idx) const 21.402 +{ 21.403 + if(idx < 0 || idx >= (int)bones.size()) { 21.404 + return 0; 21.405 + } 21.406 + return bones[idx]; 21.407 +} 21.408 + 21.409 +int Mesh::get_bones_count() const 21.410 +{ 21.411 + return (int)bones.size(); 21.412 +} 21.413 + 21.414 +void Mesh::draw() const 21.415 +{ 21.416 + const ShaderProg *cur_sdr = get_current_shader(); 21.417 +#ifdef GL_ES_VERSION_2_0 21.418 + if(!cur_sdr) { 21.419 + error_log("%s: CrippledGL ES can't draw without a shader\n", __FUNCTION__); 21.420 + return; 21.421 + } 21.422 +#endif 21.423 + 21.424 + ((Mesh*)this)->update_buffers(); 21.425 + 21.426 + if(!vattr[MESH_ATTR_VERTEX].vbo_valid) { 21.427 + error_log("%s: invalid vertex buffer\n", __FUNCTION__); 21.428 + return; 21.429 + } 21.430 + 21.431 + if(cur_sdr) { 21.432 + // rendering with shaders 21.433 + if(global_sdr_loc[MESH_ATTR_VERTEX] == -1) { 21.434 + error_log("%s: shader attribute location for vertices unset\n", __FUNCTION__); 21.435 + return; 21.436 + } 21.437 + 21.438 + for(int i=0; i<NUM_MESH_ATTR; i++) { 21.439 + int loc = global_sdr_loc[i]; 21.440 + if(loc >= 0 && vattr[i].vbo_valid) { 21.441 + glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo); 21.442 + glVertexAttribPointer(loc, vattr[i].nelem, GL_FLOAT, GL_FALSE, 0, 0); 21.443 + glEnableVertexAttribArray(loc); 21.444 + } 21.445 + } 21.446 + } else { 21.447 +#ifndef GL_ES_VERSION_2_0 21.448 + // rendering with fixed-function (not available in GLES2) 21.449 + glBindBuffer(GL_ARRAY_BUFFER, vattr[MESH_ATTR_VERTEX].vbo); 21.450 + glVertexPointer(vattr[MESH_ATTR_VERTEX].nelem, GL_FLOAT, 0, 0); 21.451 + glEnableClientState(GL_VERTEX_ARRAY); 21.452 + 21.453 + if(vattr[MESH_ATTR_NORMAL].vbo_valid) { 21.454 + glBindBuffer(GL_ARRAY_BUFFER, vattr[MESH_ATTR_NORMAL].vbo); 21.455 + glNormalPointer(GL_FLOAT, 0, 0); 21.456 + glEnableClientState(GL_NORMAL_ARRAY); 21.457 + } 21.458 + if(vattr[MESH_ATTR_TEXCOORD].vbo_valid) { 21.459 + glBindBuffer(GL_ARRAY_BUFFER, vattr[MESH_ATTR_TEXCOORD].vbo); 21.460 + glTexCoordPointer(vattr[MESH_ATTR_TEXCOORD].nelem, GL_FLOAT, 0, 0); 21.461 + glEnableClientState(GL_TEXTURE_COORD_ARRAY); 21.462 + } 21.463 + if(vattr[MESH_ATTR_COLOR].vbo_valid) { 21.464 + glBindBuffer(GL_ARRAY_BUFFER, vattr[MESH_ATTR_COLOR].vbo); 21.465 + glColorPointer(vattr[MESH_ATTR_COLOR].nelem, GL_FLOAT, 0, 0); 21.466 + glEnableClientState(GL_COLOR_ARRAY); 21.467 + } 21.468 +#endif 21.469 + } 21.470 + glBindBuffer(GL_ARRAY_BUFFER, 0); 21.471 + 21.472 + if(ibo_valid) { 21.473 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 21.474 + glDrawElements(GL_TRIANGLES, nfaces * 3, GL_UNSIGNED_INT, 0); 21.475 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 21.476 + } else { 21.477 + glDrawArrays(GL_TRIANGLES, 0, nverts); 21.478 + } 21.479 + 21.480 + if(cur_sdr) { 21.481 + // rendered with shaders 21.482 + for(int i=0; i<NUM_MESH_ATTR; i++) { 21.483 + int loc = global_sdr_loc[i]; 21.484 + if(loc >= 0 && vattr[i].vbo_valid) { 21.485 + glDisableVertexAttribArray(loc); 21.486 + } 21.487 + } 21.488 + } else { 21.489 +#ifndef GL_ES_VERSION_2_0 21.490 + // rendered with fixed-function 21.491 + glDisableClientState(GL_VERTEX_ARRAY); 21.492 + if(vattr[MESH_ATTR_NORMAL].vbo_valid) { 21.493 + glDisableClientState(GL_NORMAL_ARRAY); 21.494 + } 21.495 + if(vattr[MESH_ATTR_TEXCOORD].vbo_valid) { 21.496 + glDisableClientState(GL_TEXTURE_COORD_ARRAY); 21.497 + } 21.498 + if(vattr[MESH_ATTR_COLOR].vbo_valid) { 21.499 + glDisableClientState(GL_COLOR_ARRAY); 21.500 + } 21.501 +#endif 21.502 + } 21.503 +} 21.504 + 21.505 +void Mesh::draw_wire() const 21.506 +{ 21.507 + ((Mesh*)this)->update_wire_ibo(); 21.508 + 21.509 + if(!vattr[MESH_ATTR_VERTEX].vbo_valid || !wire_ibo_valid) { 21.510 + error_log("%s: invalid vertex buffer\n", __FUNCTION__); 21.511 + return; 21.512 + } 21.513 + if(global_sdr_loc[MESH_ATTR_VERTEX] == -1) { 21.514 + error_log("%s: shader attribute location for vertices unset\n", __FUNCTION__); 21.515 + return; 21.516 + } 21.517 + 21.518 + for(int i=0; i<NUM_MESH_ATTR; i++) { 21.519 + int loc = global_sdr_loc[i]; 21.520 + if(loc >= 0 && vattr[i].vbo_valid) { 21.521 + glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo); 21.522 + glVertexAttribPointer(loc, vattr[i].nelem, GL_FLOAT, GL_FALSE, 0, 0); 21.523 + glEnableVertexAttribArray(loc); 21.524 + } 21.525 + } 21.526 + glBindBuffer(GL_ARRAY_BUFFER, 0); 21.527 + 21.528 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, wire_ibo); 21.529 + glDrawElements(GL_LINES, nfaces * 6, GL_UNSIGNED_INT, 0); 21.530 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 21.531 + 21.532 + for(int i=0; i<NUM_MESH_ATTR; i++) { 21.533 + int loc = global_sdr_loc[i]; 21.534 + if(loc >= 0 && vattr[i].vbo_valid) { 21.535 + glDisableVertexAttribArray(loc); 21.536 + } 21.537 + } 21.538 +} 21.539 + 21.540 +void Mesh::draw_vertices() const 21.541 +{ 21.542 + ((Mesh*)this)->update_buffers(); 21.543 + 21.544 + if(!vattr[MESH_ATTR_VERTEX].vbo_valid) { 21.545 + error_log("%s: invalid vertex buffer\n", __FUNCTION__); 21.546 + return; 21.547 + } 21.548 + if(global_sdr_loc[MESH_ATTR_VERTEX] == -1) { 21.549 + error_log("%s: shader attribute location for vertices unset\n", __FUNCTION__); 21.550 + return; 21.551 + } 21.552 + 21.553 + for(int i=0; i<NUM_MESH_ATTR; i++) { 21.554 + int loc = global_sdr_loc[i]; 21.555 + if(loc >= 0 && vattr[i].vbo_valid) { 21.556 + glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo); 21.557 + glVertexAttribPointer(loc, vattr[i].nelem, GL_FLOAT, GL_FALSE, 0, 0); 21.558 + glEnableVertexAttribArray(loc); 21.559 + } 21.560 + } 21.561 + glBindBuffer(GL_ARRAY_BUFFER, 0); 21.562 + 21.563 + glDrawArrays(GL_POINTS, 0, nverts); 21.564 + 21.565 + for(int i=0; i<NUM_MESH_ATTR; i++) { 21.566 + int loc = global_sdr_loc[i]; 21.567 + if(loc >= 0 && vattr[i].vbo_valid) { 21.568 + glDisableVertexAttribArray(loc); 21.569 + } 21.570 + } 21.571 +} 21.572 + 21.573 +void Mesh::draw_normals() const 21.574 +{ 21.575 +#ifdef USE_OLDGL 21.576 + int vert_loc = global_sdr_loc[MESH_ATTR_VERTEX]; 21.577 + Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX); 21.578 + Vector3 *norm = (Vector3*)get_attrib_data(MESH_ATTR_NORMAL); 21.579 + 21.580 + if(!varr || !norm || vert_loc < 0) { 21.581 + return; 21.582 + } 21.583 + 21.584 + glBegin(GL_LINES); 21.585 + for(size_t i=0; i<nverts; i++) { 21.586 + glVertexAttrib3f(vert_loc, varr[i].x, varr[i].y, varr[i].z); 21.587 + Vector3 end = varr[i] + norm[i] * vis_vecsize; 21.588 + glVertexAttrib3f(vert_loc, end.x, end.y, end.z); 21.589 + } 21.590 + glEnd(); 21.591 + 21.592 +#endif // USE_OLDGL 21.593 +} 21.594 + 21.595 +void Mesh::draw_tangents() const 21.596 +{ 21.597 +#ifdef USE_OLDGL 21.598 + int vert_loc = global_sdr_loc[MESH_ATTR_VERTEX]; 21.599 + Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX); 21.600 + Vector3 *tang = (Vector3*)get_attrib_data(MESH_ATTR_TANGENT); 21.601 + 21.602 + if(!varr || !tang || vert_loc < 0) { 21.603 + return; 21.604 + } 21.605 + 21.606 + glBegin(GL_LINES); 21.607 + for(size_t i=0; i<nverts; i++) { 21.608 + glVertexAttrib3f(vert_loc, varr[i].x, varr[i].y, varr[i].z); 21.609 + Vector3 end = varr[i] + tang[i] * vis_vecsize; 21.610 + glVertexAttrib3f(vert_loc, end.x, end.y, end.z); 21.611 + } 21.612 + glEnd(); 21.613 + 21.614 +#endif // USE_OLDGL 21.615 +} 21.616 + 21.617 +void Mesh::get_aabbox(Vector3 *vmin, Vector3 *vmax) const 21.618 +{ 21.619 + if(!aabb_valid) { 21.620 + ((Mesh*)this)->calc_aabb(); 21.621 + } 21.622 + *vmin = aabb.min; 21.623 + *vmax = aabb.max; 21.624 +} 21.625 + 21.626 +const AABox &Mesh::get_aabbox() const 21.627 +{ 21.628 + if(!aabb_valid) { 21.629 + ((Mesh*)this)->calc_aabb(); 21.630 + } 21.631 + return aabb; 21.632 +} 21.633 + 21.634 +float Mesh::get_bsphere(Vector3 *center, float *rad) const 21.635 +{ 21.636 + if(!bsph_valid) { 21.637 + ((Mesh*)this)->calc_bsph(); 21.638 + } 21.639 + *center = bsph.center; 21.640 + *rad = bsph.radius; 21.641 + return bsph.radius; 21.642 +} 21.643 + 21.644 +const Sphere &Mesh::get_bsphere() const 21.645 +{ 21.646 + if(!bsph_valid) { 21.647 + ((Mesh*)this)->calc_bsph(); 21.648 + } 21.649 + return bsph; 21.650 +} 21.651 + 21.652 +/// static function 21.653 +void Mesh::set_intersect_mode(unsigned int mode) 21.654 +{ 21.655 + Mesh::intersect_mode = mode; 21.656 +} 21.657 + 21.658 +/// static function 21.659 +unsigned int Mesh::get_intersect_mode() 21.660 +{ 21.661 + return Mesh::intersect_mode; 21.662 +} 21.663 + 21.664 +/// static function 21.665 +void Mesh::set_vertex_select_distance(float dist) 21.666 +{ 21.667 + Mesh::vertex_sel_dist = dist; 21.668 +} 21.669 + 21.670 +/// static function 21.671 +float Mesh::get_vertex_select_distance() 21.672 +{ 21.673 + return Mesh::vertex_sel_dist; 21.674 +} 21.675 + 21.676 +bool Mesh::intersect(const Ray &ray, HitPoint *hit) const 21.677 +{ 21.678 + assert((Mesh::intersect_mode & (ISECT_VERTICES | ISECT_FACE)) != (ISECT_VERTICES | ISECT_FACE)); 21.679 + 21.680 + const Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX); 21.681 + const Vector3 *narr = (Vector3*)get_attrib_data(MESH_ATTR_NORMAL); 21.682 + if(!varr) { 21.683 + return false; 21.684 + } 21.685 + const unsigned int *idxarr = get_index_data(); 21.686 + 21.687 + // first test with the bounding box 21.688 + AABox box; 21.689 + get_aabbox(&box.min, &box.max); 21.690 + if(!box.intersect(ray)) { 21.691 + return false; 21.692 + } 21.693 + 21.694 + HitPoint nearest_hit; 21.695 + nearest_hit.dist = FLT_MAX; 21.696 + nearest_hit.obj = 0; 21.697 + 21.698 + if(Mesh::intersect_mode & ISECT_VERTICES) { 21.699 + // we asked for "intersections" with the vertices of the mesh 21.700 + long nearest_vidx = -1; 21.701 + float thres_sq = Mesh::vertex_sel_dist * Mesh::vertex_sel_dist; 21.702 + 21.703 + for(unsigned int i=0; i<nverts; i++) { 21.704 + 21.705 + if((Mesh::intersect_mode & ISECT_FRONT) && dot_product(narr[i], ray.dir) > 0) { 21.706 + continue; 21.707 + } 21.708 + 21.709 + // project the vertex onto the ray line 21.710 + float t = dot_product(varr[i] - ray.origin, ray.dir); 21.711 + Vector3 vproj = ray.origin + ray.dir * t; 21.712 + 21.713 + float dist_sq = (vproj - varr[i]).length_sq(); 21.714 + if(dist_sq < thres_sq) { 21.715 + if(!hit) { 21.716 + return true; 21.717 + } 21.718 + if(t < nearest_hit.dist) { 21.719 + nearest_hit.dist = t; 21.720 + nearest_vidx = i; 21.721 + } 21.722 + } 21.723 + } 21.724 + 21.725 + if(nearest_vidx != -1) { 21.726 + hitvert = varr[nearest_vidx]; 21.727 + nearest_hit.obj = &hitvert; 21.728 + } 21.729 + 21.730 + } else { 21.731 + // regular intersection test with polygons 21.732 + 21.733 + for(unsigned int i=0; i<nfaces; i++) { 21.734 + Triangle face(i, varr, idxarr); 21.735 + 21.736 + // ignore back-facing polygons if the mode flags include ISECT_FRONT 21.737 + if((Mesh::intersect_mode & ISECT_FRONT) && dot_product(face.get_normal(), ray.dir) > 0) { 21.738 + continue; 21.739 + } 21.740 + 21.741 + HitPoint fhit; 21.742 + if(face.intersect(ray, hit ? &fhit : 0)) { 21.743 + if(!hit) { 21.744 + return true; 21.745 + } 21.746 + if(fhit.dist < nearest_hit.dist) { 21.747 + nearest_hit = fhit; 21.748 + hitface = face; 21.749 + } 21.750 + } 21.751 + } 21.752 + } 21.753 + 21.754 + if(nearest_hit.obj) { 21.755 + if(hit) { 21.756 + *hit = nearest_hit; 21.757 + 21.758 + // if we are interested in the mesh and not the faces set obj to this 21.759 + if(Mesh::intersect_mode & ISECT_FACE) { 21.760 + hit->obj = &hitface; 21.761 + } else if(Mesh::intersect_mode & ISECT_VERTICES) { 21.762 + hit->obj = &hitvert; 21.763 + } else { 21.764 + hit->obj = this; 21.765 + } 21.766 + } 21.767 + return true; 21.768 + } 21.769 + return false; 21.770 +} 21.771 + 21.772 + 21.773 +// ------ private member functions ------ 21.774 + 21.775 +void Mesh::calc_aabb() 21.776 +{ 21.777 + // the cast is to force calling the const version which doesn't invalidate 21.778 + if(!((const Mesh*)this)->get_attrib_data(MESH_ATTR_VERTEX)) { 21.779 + return; 21.780 + } 21.781 + 21.782 + aabb.min = Vector3(FLT_MAX, FLT_MAX, FLT_MAX); 21.783 + aabb.max = -aabb.min; 21.784 + 21.785 + for(unsigned int i=0; i<nverts; i++) { 21.786 + Vector4 v = get_attrib(MESH_ATTR_VERTEX, i); 21.787 + for(int j=0; j<3; j++) { 21.788 + if(v[j] < aabb.min[j]) { 21.789 + aabb.min[j] = v[j]; 21.790 + } 21.791 + if(v[j] > aabb.max[j]) { 21.792 + aabb.max[j] = v[j]; 21.793 + } 21.794 + } 21.795 + } 21.796 + aabb_valid = true; 21.797 +} 21.798 + 21.799 +void Mesh::calc_bsph() 21.800 +{ 21.801 + // the cast is to force calling the const version which doesn't invalidate 21.802 + if(!((const Mesh*)this)->get_attrib_data(MESH_ATTR_VERTEX)) { 21.803 + return; 21.804 + } 21.805 + 21.806 + Vector3 v; 21.807 + bsph.center = Vector3(0, 0, 0); 21.808 + 21.809 + // first find the center 21.810 + for(unsigned int i=0; i<nverts; i++) { 21.811 + v = get_attrib(MESH_ATTR_VERTEX, i); 21.812 + bsph.center += v; 21.813 + } 21.814 + bsph.center /= (float)nverts; 21.815 + 21.816 + bsph.radius = 0.0f; 21.817 + for(unsigned int i=0; i<nverts; i++) { 21.818 + v = get_attrib(MESH_ATTR_VERTEX, i); 21.819 + float dist_sq = (v - bsph.center).length_sq(); 21.820 + if(dist_sq > bsph.radius) { 21.821 + bsph.radius = dist_sq; 21.822 + } 21.823 + } 21.824 + bsph.radius = sqrt(bsph.radius); 21.825 + 21.826 + bsph_valid = true; 21.827 +} 21.828 + 21.829 +void Mesh::update_buffers() 21.830 +{ 21.831 + for(int i=0; i<NUM_MESH_ATTR; i++) { 21.832 + if(has_attrib(i) && !vattr[i].vbo_valid) { 21.833 + glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo); 21.834 + glBufferData(GL_ARRAY_BUFFER, nverts * vattr[i].nelem * sizeof(float), &vattr[i].data[0], GL_STATIC_DRAW); 21.835 + vattr[i].vbo_valid = true; 21.836 + } 21.837 + } 21.838 + glBindBuffer(GL_ARRAY_BUFFER, 0); 21.839 + 21.840 + if(idata_valid && !ibo_valid) { 21.841 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 21.842 + glBufferData(GL_ELEMENT_ARRAY_BUFFER, nfaces * 3 * sizeof(unsigned int), &idata[0], GL_STATIC_DRAW); 21.843 + ibo_valid = true; 21.844 + } 21.845 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 21.846 +} 21.847 + 21.848 +void Mesh::update_wire_ibo() 21.849 +{ 21.850 + update_buffers(); 21.851 + 21.852 + if(wire_ibo_valid) { 21.853 + return; 21.854 + } 21.855 + 21.856 + if(!wire_ibo) { 21.857 + glGenBuffers(1, &wire_ibo); 21.858 + } 21.859 + 21.860 + unsigned int *wire_idxarr = new unsigned int[nfaces * 6]; 21.861 + unsigned int *dest = wire_idxarr; 21.862 + 21.863 + if(ibo_valid) { 21.864 + // we're dealing with an indexed mesh 21.865 + const unsigned int *idxarr = ((const Mesh*)this)->get_index_data(); 21.866 + 21.867 + for(unsigned int i=0; i<nfaces; i++) { 21.868 + *dest++ = idxarr[0]; 21.869 + *dest++ = idxarr[1]; 21.870 + *dest++ = idxarr[1]; 21.871 + *dest++ = idxarr[2]; 21.872 + *dest++ = idxarr[2]; 21.873 + *dest++ = idxarr[0]; 21.874 + idxarr += 3; 21.875 + } 21.876 + } else { 21.877 + // not an indexed mesh ... 21.878 + for(unsigned int i=0; i<nfaces; i++) { 21.879 + int vidx = i * 3; 21.880 + *dest++ = vidx; 21.881 + *dest++ = vidx + 1; 21.882 + *dest++ = vidx + 1; 21.883 + *dest++ = vidx + 2; 21.884 + *dest++ = vidx + 2; 21.885 + *dest++ = vidx; 21.886 + } 21.887 + } 21.888 + 21.889 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, wire_ibo); 21.890 + glBufferData(GL_ELEMENT_ARRAY_BUFFER, nfaces * 6 * sizeof(unsigned int), wire_idxarr, GL_STATIC_DRAW); 21.891 + delete [] wire_idxarr; 21.892 + wire_ibo_valid = true; 21.893 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 21.894 +} 21.895 + 21.896 + 21.897 +// ------ class Triangle ------ 21.898 +Triangle::Triangle() 21.899 +{ 21.900 + normal_valid = false; 21.901 + id = -1; 21.902 +} 21.903 + 21.904 +Triangle::Triangle(const Vector3 &v0, const Vector3 &v1, const Vector3 &v2) 21.905 +{ 21.906 + v[0] = v0; 21.907 + v[1] = v1; 21.908 + v[2] = v2; 21.909 + normal_valid = false; 21.910 + id = -1; 21.911 +} 21.912 + 21.913 +Triangle::Triangle(int n, const Vector3 *varr, const unsigned int *idxarr) 21.914 +{ 21.915 + if(idxarr) { 21.916 + v[0] = varr[idxarr[n * 3]]; 21.917 + v[1] = varr[idxarr[n * 3 + 1]]; 21.918 + v[2] = varr[idxarr[n * 3 + 2]]; 21.919 + } else { 21.920 + v[0] = varr[n * 3]; 21.921 + v[1] = varr[n * 3 + 1]; 21.922 + v[2] = varr[n * 3 + 2]; 21.923 + } 21.924 + normal_valid = false; 21.925 + id = n; 21.926 +} 21.927 + 21.928 +void Triangle::calc_normal() 21.929 +{ 21.930 + normal = cross_product(v[1] - v[0], v[2] - v[0]).normalized(); 21.931 + normal_valid = true; 21.932 +} 21.933 + 21.934 +const Vector3 &Triangle::get_normal() const 21.935 +{ 21.936 + if(!normal_valid) { 21.937 + ((Triangle*)this)->calc_normal(); 21.938 + } 21.939 + return normal; 21.940 +} 21.941 + 21.942 +void Triangle::transform(const Matrix4x4 &xform) 21.943 +{ 21.944 + v[0].transform(xform); 21.945 + v[1].transform(xform); 21.946 + v[2].transform(xform); 21.947 + normal_valid = false; 21.948 +} 21.949 + 21.950 +void Triangle::draw() const 21.951 +{ 21.952 + Vector3 n[3]; 21.953 + n[0] = get_normal(); 21.954 + n[1] = get_normal(); 21.955 + n[2] = get_normal(); 21.956 + 21.957 + int vloc = Mesh::get_attrib_location(MESH_ATTR_VERTEX); 21.958 + int nloc = Mesh::get_attrib_location(MESH_ATTR_NORMAL); 21.959 + 21.960 + glEnableVertexAttribArray(vloc); 21.961 + glVertexAttribPointer(vloc, 3, GL_FLOAT, GL_FALSE, 0, &v[0].x); 21.962 + glVertexAttribPointer(nloc, 3, GL_FLOAT, GL_FALSE, 0, &n[0].x); 21.963 + 21.964 + glDrawArrays(GL_TRIANGLES, 0, 3); 21.965 + 21.966 + glDisableVertexAttribArray(vloc); 21.967 + glDisableVertexAttribArray(nloc); 21.968 + CHECKGLERR; 21.969 +} 21.970 + 21.971 +void Triangle::draw_wire() const 21.972 +{ 21.973 + static const int idxarr[] = {0, 1, 1, 2, 2, 0}; 21.974 + int vloc = Mesh::get_attrib_location(MESH_ATTR_VERTEX); 21.975 + 21.976 + glEnableVertexAttribArray(vloc); 21.977 + glVertexAttribPointer(vloc, 3, GL_FLOAT, GL_FALSE, 0, &v[0].x); 21.978 + 21.979 + glDrawElements(GL_LINES, 6, GL_UNSIGNED_INT, idxarr); 21.980 + 21.981 + glDisableVertexAttribArray(vloc); 21.982 + CHECKGLERR; 21.983 +} 21.984 + 21.985 +Vector3 Triangle::calc_barycentric(const Vector3 &pos) const 21.986 +{ 21.987 + Vector3 norm = get_normal(); 21.988 + 21.989 + float area_sq = fabs(dot_product(cross_product(v[1] - v[0], v[2] - v[0]), norm)); 21.990 + if(area_sq < 1e-5) { 21.991 + return Vector3(0, 0, 0); 21.992 + } 21.993 + 21.994 + float asq0 = fabs(dot_product(cross_product(v[1] - pos, v[2] - pos), norm)); 21.995 + float asq1 = fabs(dot_product(cross_product(v[2] - pos, v[0] - pos), norm)); 21.996 + float asq2 = fabs(dot_product(cross_product(v[0] - pos, v[1] - pos), norm)); 21.997 + 21.998 + return Vector3(asq0 / area_sq, asq1 / area_sq, asq2 / area_sq); 21.999 +} 21.1000 + 21.1001 +bool Triangle::intersect(const Ray &ray, HitPoint *hit) const 21.1002 +{ 21.1003 + Vector3 normal = get_normal(); 21.1004 + 21.1005 + float ndotdir = dot_product(ray.dir, normal); 21.1006 + if(fabs(ndotdir) < 1e-4) { 21.1007 + return false; 21.1008 + } 21.1009 + 21.1010 + Vector3 vertdir = v[0] - ray.origin; 21.1011 + float t = dot_product(normal, vertdir) / ndotdir; 21.1012 + 21.1013 + Vector3 pos = ray.origin + ray.dir * t; 21.1014 + Vector3 bary = calc_barycentric(pos); 21.1015 + 21.1016 + if(bary.x + bary.y + bary.z > 1.00001) { 21.1017 + return false; 21.1018 + } 21.1019 + 21.1020 + if(hit) { 21.1021 + hit->dist = t; 21.1022 + hit->pos = ray.origin + ray.dir * t; 21.1023 + hit->normal = normal; 21.1024 + hit->obj = this; 21.1025 + } 21.1026 + return true; 21.1027 +}
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 22.2 +++ b/src/mesh.h Sun Aug 24 09:41:24 2014 +0300 22.3 @@ -0,0 +1,210 @@ 22.4 +#ifndef MESH_H_ 22.5 +#define MESH_H_ 22.6 + 22.7 +#include <string> 22.8 +#include <vector> 22.9 +#include <vmath/vmath.h> 22.10 +#include "geom.h" 22.11 + 22.12 +enum { 22.13 + MESH_ATTR_VERTEX, 22.14 + MESH_ATTR_NORMAL, 22.15 + MESH_ATTR_TANGENT, 22.16 + MESH_ATTR_TEXCOORD, 22.17 + MESH_ATTR_COLOR, 22.18 + MESH_ATTR_BONEWEIGHTS, 22.19 + MESH_ATTR_BONEIDX, 22.20 + 22.21 + NUM_MESH_ATTR 22.22 +}; 22.23 + 22.24 +// intersection mode flags 22.25 +enum { 22.26 + ISECT_DEFAULT = 0, // default (whole mesh, all intersections) 22.27 + ISECT_FRONT = 1, // front-faces only 22.28 + ISECT_FACE = 2, // return intersected face pointer instead of mesh 22.29 + ISECT_VERTICES = 4 // return (?) TODO 22.30 +}; 22.31 + 22.32 +class XFormNode; 22.33 + 22.34 + 22.35 +class Triangle { 22.36 +public: 22.37 + Vector3 v[3]; 22.38 + Vector3 normal; 22.39 + bool normal_valid; 22.40 + int id; 22.41 + 22.42 + Triangle(); 22.43 + Triangle(const Vector3 &v0, const Vector3 &v1, const Vector3 &v2); 22.44 + Triangle(int n, const Vector3 *varr, const unsigned int *idxarr = 0); 22.45 + 22.46 + /// calculate normal (quite expensive) 22.47 + void calc_normal(); 22.48 + const Vector3 &get_normal() const; 22.49 + 22.50 + void transform(const Matrix4x4 &xform); 22.51 + 22.52 + void draw() const; 22.53 + void draw_wire() const; 22.54 + 22.55 + /// calculate barycentric coordinates of a point 22.56 + Vector3 calc_barycentric(const Vector3 &pos) const; 22.57 + 22.58 + bool intersect(const Ray &ray, HitPoint *hit = 0) const; 22.59 +}; 22.60 + 22.61 + 22.62 +class Mesh { 22.63 +private: 22.64 + std::string name; 22.65 + unsigned int nverts, nfaces; 22.66 + 22.67 + // current value for each attribute for the immedate mode 22.68 + // interface. 22.69 + Vector4 cur_val[NUM_MESH_ATTR]; 22.70 + 22.71 + unsigned int buffer_objects[NUM_MESH_ATTR + 1]; 22.72 + 22.73 + // vertex attribute data and buffer objects 22.74 + struct { 22.75 + int nelem; // number of elements per attribute range: [1, 4] 22.76 + std::vector<float> data; 22.77 + unsigned int vbo; 22.78 + mutable bool vbo_valid; // if this is false, the vbo needs updating from the data 22.79 + mutable bool data_valid; // if this is false, the data needs to be pulled from the vbo 22.80 + //int sdr_loc; 22.81 + } vattr[NUM_MESH_ATTR]; 22.82 + 22.83 + static int global_sdr_loc[NUM_MESH_ATTR]; 22.84 + 22.85 + std::vector<XFormNode*> bones; // bones affecting this mesh 22.86 + 22.87 + // index data and buffer object 22.88 + std::vector<unsigned int> idata; 22.89 + unsigned int ibo; 22.90 + mutable bool ibo_valid; 22.91 + mutable bool idata_valid; 22.92 + 22.93 + // index buffer object for wireframe rendering (constructed on demand) 22.94 + unsigned int wire_ibo; 22.95 + mutable bool wire_ibo_valid; 22.96 + 22.97 + // axis-aligned bounding box 22.98 + mutable AABox aabb; 22.99 + mutable bool aabb_valid; 22.100 + 22.101 + // bounding sphere 22.102 + mutable Sphere bsph; 22.103 + mutable bool bsph_valid; 22.104 + 22.105 + // keeps the last intersected face 22.106 + mutable Triangle hitface; 22.107 + // keeps the last intersected vertex position 22.108 + mutable Vector3 hitvert; 22.109 + 22.110 + void calc_aabb(); 22.111 + void calc_bsph(); 22.112 + 22.113 + static unsigned int intersect_mode; 22.114 + static float vertex_sel_dist; 22.115 + 22.116 + static float vis_vecsize; 22.117 + 22.118 + /// update the VBOs after data has changed (invalid vbo/ibo) 22.119 + void update_buffers(); 22.120 + /// construct/update the wireframe index buffer (called from draw_wire). 22.121 + void update_wire_ibo(); 22.122 + 22.123 + 22.124 +public: 22.125 + Mesh(); 22.126 + ~Mesh(); 22.127 + 22.128 + void set_name(const char *name); 22.129 + const char *get_name() const; 22.130 + 22.131 + bool has_attrib(int attr) const; 22.132 + 22.133 + // clears everything about this mesh, and returns to the newly constructed state 22.134 + void clear(); 22.135 + 22.136 + // access the vertex attribute data 22.137 + // if vdata == 0, space is just allocated 22.138 + float *set_attrib_data(int attrib, int nelem, unsigned int num, const float *vdata = 0); // invalidates vbo 22.139 + float *get_attrib_data(int attrib); // invalidates vbo 22.140 + const float *get_attrib_data(int attrib) const; 22.141 + 22.142 + // simple access to any particular attribute 22.143 + void set_attrib(int attrib, int idx, const Vector4 &v); // invalidates vbo 22.144 + Vector4 get_attrib(int attrib, int idx) const; 22.145 + 22.146 + // ... same for index data 22.147 + unsigned int *set_index_data(int num, const unsigned int *indices = 0); // invalidates ibo 22.148 + unsigned int *get_index_data(); // invalidates ibo 22.149 + const unsigned int *get_index_data() const; 22.150 + 22.151 + void append(const Mesh &mesh); 22.152 + 22.153 + // immediate-mode style mesh construction interface 22.154 + void vertex(float x, float y, float z); 22.155 + void normal(float nx, float ny, float nz); 22.156 + void tangent(float tx, float ty, float tz); 22.157 + void texcoord(float u, float v, float w); 22.158 + void boneweights(float w1, float w2, float w3, float w4); 22.159 + void boneidx(int idx1, int idx2, int idx3, int idx4); 22.160 + 22.161 + /* apply a transformation to the vertices and its inverse-transpose 22.162 + * to the normals and tangents. 22.163 + */ 22.164 + void apply_xform(const Matrix4x4 &xform); 22.165 + void apply_xform(const Matrix4x4 &xform, const Matrix4x4 &dir_xform); 22.166 + 22.167 + // adds a bone and returns its index 22.168 + int add_bone(XFormNode *bone); 22.169 + const XFormNode *get_bone(int idx) const; 22.170 + int get_bones_count() const; 22.171 + 22.172 + // access the shader attribute locations 22.173 + static void set_attrib_location(int attr, int loc); 22.174 + static int get_attrib_location(int attr); 22.175 + static void clear_attrib_locations(); 22.176 + 22.177 + static void set_vis_vecsize(float sz); 22.178 + static float get_vis_vecsize(); 22.179 + 22.180 + void draw() const; 22.181 + void draw_wire() const; 22.182 + void draw_vertices() const; 22.183 + void draw_normals() const; 22.184 + void draw_tangents() const; 22.185 + 22.186 + /** get the bounding box in local space. The result will be cached, and subsequent 22.187 + * calls will return the same box. The cache gets invalidated by any functions that can affect 22.188 + * the vertex data (non-const variant of get_attrib_data(MESH_ATTR_VERTEX, ...) included). 22.189 + * @{ */ 22.190 + void get_aabbox(Vector3 *vmin, Vector3 *vmax) const; 22.191 + const AABox &get_aabbox() const; 22.192 + /// @} 22.193 + 22.194 + /** get the bounding sphere in local space. The result will be cached, and subsequent 22.195 + * calls will return the same box. The cache gets invalidated by any functions that can affect 22.196 + * the vertex data (non-const variant of get_attrib_data(MESH_ATTR_VERTEX, ...) included). 22.197 + * @{ */ 22.198 + float get_bsphere(Vector3 *center, float *rad) const; 22.199 + const Sphere &get_bsphere() const; 22.200 + 22.201 + static void set_intersect_mode(unsigned int mode); 22.202 + static unsigned int get_intersect_mode(); 22.203 + static void set_vertex_select_distance(float dist); 22.204 + static float get_vertex_select_distance(); 22.205 + 22.206 + /** Find the intersection between the mesh and a ray. 22.207 + * XXX Brute force at the moment, not intended to be used for anything other than picking in tools. 22.208 + * If you intend to use it in a speed-critical part of the code, you'll *have* to optimize it! 22.209 + */ 22.210 + bool intersect(const Ray &ray, HitPoint *hit = 0) const; 22.211 +}; 22.212 + 22.213 +#endif // MESH_H_
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 23.2 +++ b/src/object.cc Sun Aug 24 09:41:24 2014 +0300 23.3 @@ -0,0 +1,285 @@ 23.4 +#include <float.h> 23.5 +#include "object.h" 23.6 +#include "opengl.h" 23.7 +#include "unistate.h" 23.8 +#include "logger.h" 23.9 + 23.10 + 23.11 +static void destroy_all_rec(XFormNode *node); 23.12 +static void get_all_meshes_rec(XFormNode *node, std::list<Mesh*> *reslist); 23.13 + 23.14 +DrawMode Object::draw_mode = DRAW_DEFAULT; 23.15 + 23.16 +Object::Object() 23.17 +{ 23.18 + mesh = 0; 23.19 +} 23.20 + 23.21 +void Object::destroy_all() 23.22 +{ 23.23 + destroy_all_rec(this); 23.24 +} 23.25 + 23.26 +static void destroy_all_rec(XFormNode *node) 23.27 +{ 23.28 + if(!node) { 23.29 + return; 23.30 + } 23.31 + 23.32 + for(int i=0; i<node->get_children_count(); i++) { 23.33 + destroy_all_rec(node->get_child(i)); 23.34 + } 23.35 + delete node; 23.36 +} 23.37 + 23.38 +void Object::set_mesh(Mesh *m) 23.39 +{ 23.40 + mesh = m; 23.41 +} 23.42 + 23.43 +Mesh *Object::get_mesh() 23.44 +{ 23.45 + return mesh; 23.46 +} 23.47 + 23.48 +const Mesh *Object::get_mesh() const 23.49 +{ 23.50 + return mesh; 23.51 +} 23.52 + 23.53 +std::list<Mesh*> Object::get_all_meshes() 23.54 +{ 23.55 + std::list<Mesh*> meshes; 23.56 + get_all_meshes_rec(this, &meshes); 23.57 + return meshes; 23.58 +} 23.59 + 23.60 +std::list<const Mesh*> Object::get_all_meshes() const 23.61 +{ 23.62 + std::list<const Mesh*> meshes; 23.63 + get_all_meshes_rec((Object*)this, (std::list<Mesh*>*)&meshes); 23.64 + return meshes; 23.65 +} 23.66 + 23.67 +static void get_all_meshes_rec(XFormNode *node, std::list<Mesh*> *reslist) 23.68 +{ 23.69 + if(!node) { 23.70 + return; 23.71 + } 23.72 + 23.73 + Object *obj = dynamic_cast<Object*>(node); 23.74 + if(obj) { 23.75 + Mesh *mesh = obj->get_mesh(); 23.76 + if(mesh) { 23.77 + reslist->push_back(mesh); 23.78 + } 23.79 + } 23.80 + 23.81 + for(int i=0; i<node->get_children_count(); i++) { 23.82 + get_all_meshes_rec(node->get_child(i), reslist); 23.83 + } 23.84 +} 23.85 + 23.86 +AABox Object::get_aabbox() const 23.87 +{ 23.88 + AABox box; 23.89 + 23.90 + if(mesh) { 23.91 + box = mesh->get_aabbox(); 23.92 + } else { 23.93 + box.min = Vector3(FLT_MAX, FLT_MAX, FLT_MAX); 23.94 + box.max = -box.min; 23.95 + } 23.96 + 23.97 + int num_children = get_children_count(); 23.98 + for(int i=0; i<num_children; i++) { 23.99 + const Object *obj = dynamic_cast<const Object*>(get_child(i)); 23.100 + if(obj) { 23.101 + AABox child_box = obj->get_aabbox(); 23.102 + box.set_union(&box, &child_box); 23.103 + } 23.104 + } 23.105 + return box; 23.106 +} 23.107 + 23.108 +Sphere Object::get_bsphere() const 23.109 +{ 23.110 + Sphere sph; 23.111 + bool valid = false; 23.112 + 23.113 + if(mesh) { 23.114 + sph = mesh->get_bsphere(); 23.115 + valid = true; 23.116 + } else { 23.117 + sph.radius = 0.0; 23.118 + } 23.119 + 23.120 + int num_children = get_children_count(); 23.121 + for(int i=0; i<num_children; i++) { 23.122 + const Object *obj = dynamic_cast<const Object*>(get_child(i)); 23.123 + if(obj) { 23.124 + Sphere child_sph = obj->get_bsphere(); 23.125 + if(valid) { 23.126 + sph.set_union(&sph, &child_sph); 23.127 + } else { 23.128 + sph = child_sph; 23.129 + valid = true; 23.130 + } 23.131 + } 23.132 + } 23.133 + 23.134 + return sph; 23.135 +} 23.136 + 23.137 +/*static const char *attr_name[] = { 23.138 + "attr_vertex", 23.139 + "attr_normal", 23.140 + "attr_tangent", 23.141 + "attr_texcoord", 23.142 + "attr_boneweights", 23.143 + "attr_boneidx" 23.144 +};*/ 23.145 + 23.146 +void Object::draw(long msec) const 23.147 +{ 23.148 + Matrix4x4 xform; 23.149 + get_xform(msec, &xform); 23.150 + 23.151 + set_world_matrix(xform); 23.152 + 23.153 + if(mesh) { 23.154 + /*unsigned int prog = sdrprog; 23.155 + 23.156 + if(mesh->get_bones_count() > 0) { 23.157 + prog = sdrprog_skin; 23.158 + } 23.159 + 23.160 + glUseProgram(prog); 23.161 + // get all the attribute locations 23.162 + for(int i=0; i<NUM_MESH_ATTR; i++) { 23.163 + int loc = glGetAttribLocation(prog, attr_name[i]); 23.164 + if(loc != -1) { 23.165 + Mesh::set_attrib_location(i, loc); 23.166 + } 23.167 + } 23.168 + 23.169 + setup_bones(msec); 23.170 + 23.171 + glUseProgram(prog);*/ 23.172 + 23.173 + material.setup(); 23.174 + setup_unistate(); // set all state uniforms 23.175 + 23.176 + switch(Object::draw_mode) { 23.177 + case DRAW_WIREFRAME: 23.178 + mesh->draw_wire(); 23.179 + break; 23.180 + 23.181 + case DRAW_VERTICES: 23.182 + mesh->draw_vertices(); 23.183 + break; 23.184 + 23.185 + case DRAW_DEFAULT: 23.186 + default: 23.187 + mesh->draw(); 23.188 + } 23.189 + } 23.190 + 23.191 + int num_children = get_children_count(); 23.192 + for(int i=0; i<num_children; i++) { 23.193 + const Object *obj = dynamic_cast<const Object*>(get_child(i)); 23.194 + if(obj) { 23.195 + obj->draw(msec); 23.196 + } 23.197 + } 23.198 +} 23.199 + 23.200 + 23.201 +bool Object::intersect(const Ray &inray, HitPoint *hit) const 23.202 +{ 23.203 + Ray ray = inray; 23.204 + Matrix4x4 xform, inv_xform; 23.205 + get_xform(ray.time, &xform/*, &inv_xform*/); 23.206 + ray.transform(xform.inverse()); // TODO find out what's wrong with get_xform's inv_xform and use that 23.207 + 23.208 + HitPoint nearest_hit; 23.209 + nearest_hit.dist = FLT_MAX; 23.210 + nearest_hit.obj = 0; 23.211 + 23.212 + if(mesh) { 23.213 + if(mesh->intersect(ray, hit ? &nearest_hit : 0)) { 23.214 + if(!hit) { 23.215 + return true; 23.216 + } 23.217 + 23.218 + if(Mesh::get_intersect_mode() & ISECT_FACE) { 23.219 + Triangle *face = (Triangle*)nearest_hit.obj; 23.220 + face->transform(xform); 23.221 + } else if(Mesh::get_intersect_mode() & ISECT_VERTICES) { 23.222 + Vector3 *v = (Vector3*)nearest_hit.obj; 23.223 + v->transform(xform); 23.224 + } else { 23.225 + nearest_hit.obj = this; 23.226 + } 23.227 + } 23.228 + } 23.229 + 23.230 + int num_children = get_children_count(); 23.231 + for(int i=0; i<num_children; i++) { 23.232 + const Object *obj = dynamic_cast<const Object*>(get_child(i)); 23.233 + 23.234 + HitPoint chit; 23.235 + if(obj && obj->intersect(inray, hit ? &chit : 0)) { 23.236 + if(!hit) { 23.237 + return true; 23.238 + } 23.239 + 23.240 + if(chit.dist < nearest_hit.dist) { 23.241 + nearest_hit = chit; 23.242 + } 23.243 + } 23.244 + } 23.245 + 23.246 + if(nearest_hit.obj) { 23.247 + if(hit) { 23.248 + *hit = nearest_hit; 23.249 + } 23.250 + return true; 23.251 + } 23.252 + return false; 23.253 +} 23.254 + 23.255 + 23.256 +bool Object::setup_bones(long msec) const 23.257 +{ 23.258 + int num_bones; 23.259 + if(!mesh || !(num_bones = mesh->get_bones_count())) { 23.260 + return false; 23.261 + } 23.262 + 23.263 + /*char uniname[32]; 23.264 + 23.265 + for(int i=0; i<num_bones; i++) { 23.266 + const XFormNode *bone = mesh->get_bone(i); 23.267 + 23.268 + Matrix4x4 xform; 23.269 + bone->get_xform(msec, &xform); 23.270 + 23.271 + xform = xform * bone->get_bone_matrix(); 23.272 + 23.273 + sprintf(uniname, "bone_xform[%d]", i); 23.274 + int loc = glGetUniformLocation(sdrprog_skin, uniname); 23.275 + if(loc == -1) { 23.276 + return false; 23.277 + } 23.278 + glUniformMatrix4fv(loc, 1, GL_TRUE, xform[0]); 23.279 + }*/ 23.280 + return true; 23.281 +} 23.282 + 23.283 +DrawMode Object::set_draw_mode(DrawMode mode) 23.284 +{ 23.285 + DrawMode prev = Object::draw_mode; 23.286 + Object::draw_mode = mode; 23.287 + return prev; 23.288 +}
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 24.2 +++ b/src/object.h Sun Aug 24 09:41:24 2014 +0300 24.3 @@ -0,0 +1,51 @@ 24.4 +#ifndef OBJECT_H_ 24.5 +#define OBJECT_H_ 24.6 + 24.7 +#include <list> 24.8 +#include "xform_node.h" 24.9 +#include "mesh.h" 24.10 +#include "material.h" 24.11 + 24.12 +enum DrawMode { 24.13 + DRAW_DEFAULT, 24.14 + DRAW_WIREFRAME, 24.15 + DRAW_VERTICES 24.16 +}; 24.17 + 24.18 + 24.19 +class Object : public XFormNode { 24.20 +private: 24.21 + Mesh *mesh; ///< no ownership, just keeping the pointer around 24.22 + static DrawMode draw_mode; 24.23 + 24.24 + bool setup_bones(long msec) const; 24.25 + 24.26 +public: 24.27 + Material material; 24.28 + 24.29 + Object(); 24.30 + 24.31 + /// destroy this object and all the hierarchy of objects hanging below it 24.32 + void destroy_all(); 24.33 + 24.34 + void set_mesh(Mesh *m); 24.35 + Mesh *get_mesh(); 24.36 + const Mesh *get_mesh() const; 24.37 + 24.38 + /// get all the meshes of the subtree rooted in this object @{ 24.39 + std::list<Mesh*> get_all_meshes(); 24.40 + std::list<const Mesh*> get_all_meshes() const; 24.41 + /// @} 24.42 + 24.43 + AABox get_aabbox() const; 24.44 + Sphere get_bsphere() const; 24.45 + 24.46 + void draw(long msec = 0) const; 24.47 + 24.48 + bool intersect(const Ray &ray, HitPoint *hit = 0) const; 24.49 + 24.50 + /// this is mostly for tools, to allow drawing only the wireframe or vertices 24.51 + static DrawMode set_draw_mode(DrawMode mode); 24.52 +}; 24.53 + 24.54 +#endif // OBJECT_H_
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 25.2 +++ b/src/scene.cc Sun Aug 24 09:41:24 2014 +0300 25.3 @@ -0,0 +1,34 @@ 25.4 +#include "scene.h" 25.5 +#include "opengl.h" 25.6 + 25.7 +Scene::~Scene() 25.8 +{ 25.9 + destroy(); 25.10 +} 25.11 + 25.12 +void Scene::destroy() 25.13 +{ 25.14 + for(size_t i=0; i<objects.size(); i++) { 25.15 + delete objects[i]; 25.16 + } 25.17 + objects.clear(); 25.18 + 25.19 + for(size_t i=0; i<meshes.size(); i++) { 25.20 + delete meshes[i]; 25.21 + } 25.22 + meshes.clear(); 25.23 +} 25.24 + 25.25 +void Scene::draw(long msec) const 25.26 +{ 25.27 + for(size_t i=0; i<objects.size(); i++) { 25.28 + objects[i]->draw(msec); 25.29 + } 25.30 + 25.31 + // if there are no objects in the scene, just draw the meshes instead 25.32 + if(objects.empty()) { 25.33 + for(size_t i=0; i<meshes.size(); i++) { 25.34 + meshes[i]->draw(); 25.35 + } 25.36 + } 25.37 +}
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/src/scene.h Sun Aug 24 09:41:24 2014 +0300 26.3 @@ -0,0 +1,25 @@ 26.4 +#ifndef SCENE_H_ 26.5 +#define SCENE_H_ 26.6 + 26.7 +#include <vector> 26.8 +#include "object.h" 26.9 +#include "light.h" 26.10 +#include "camera.h" 26.11 + 26.12 +class Scene { 26.13 +public: 26.14 + std::vector<Object*> objects; 26.15 + std::vector<Mesh*> meshes; 26.16 + std::vector<Light*> lights; 26.17 + std::vector<Camera*> cameras; 26.18 + 26.19 + // nodes can be objects, lights, cameras, or just dummy nodes 26.20 + std::vector<XFormNode*> nodes; 26.21 + 26.22 + ~Scene(); 26.23 + void destroy(); 26.24 + 26.25 + void draw(long msec = 0) const; 26.26 +}; 26.27 + 26.28 +#endif // SCENE_H_
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/src/shader.cc Sun Aug 24 09:41:24 2014 +0300 27.3 @@ -0,0 +1,671 @@ 27.4 +#include <stdio.h> 27.5 +#include <string.h> 27.6 +#include <stdarg.h> 27.7 +#include <errno.h> 27.8 +#include "opengl.h" 27.9 +#include "shader.h" 27.10 +#include "mesh.h" 27.11 +#include "logger.h" 27.12 +#include "unistate.h" 27.13 + 27.14 +#ifdef _MSC_VER 27.15 +#include <malloc.h> 27.16 +#else 27.17 +#include <alloca.h> 27.18 +#endif 27.19 + 27.20 +#ifdef __GLEW_H__ 27.21 +#define HAVE_GEOMETRY_SHADER 27.22 +#define HAVE_TESSELATION_SHADER 27.23 +#endif 27.24 + 27.25 +static std::string read_source(const char *fname); 27.26 +static void bind_standard_attr(const ShaderProg *prog); 27.27 + 27.28 +ShaderProg *ShaderProg::current; 27.29 + 27.30 +void bind_shader(const ShaderProg *sdr) 27.31 +{ 27.32 + if(sdr) { 27.33 + sdr->bind(); 27.34 + } else { 27.35 +#ifndef GL_ES_VERSION_2_0 27.36 + glUseProgram(0); 27.37 + ShaderProg::current = 0; 27.38 +#endif 27.39 + } 27.40 +} 27.41 + 27.42 +const ShaderProg *get_current_shader() 27.43 +{ 27.44 + return ShaderProg::current; 27.45 +} 27.46 + 27.47 +Shader::Shader() 27.48 +{ 27.49 + sdr = type = 0; 27.50 +} 27.51 + 27.52 +Shader::~Shader() 27.53 +{ 27.54 + destroy(); 27.55 +} 27.56 + 27.57 +unsigned int Shader::get_id() const 27.58 +{ 27.59 + return sdr; 27.60 +} 27.61 + 27.62 +void Shader::set_name(const char *name) 27.63 +{ 27.64 + this->name = std::string(name); 27.65 +} 27.66 + 27.67 +const char *Shader::get_name() const 27.68 +{ 27.69 + return name.c_str(); 27.70 +} 27.71 + 27.72 +bool Shader::create(const char *src, unsigned int type) 27.73 +{ 27.74 +#if !GL_ES_VERSION_2_0 27.75 + const char *src_arr[] = {src}; 27.76 +#else 27.77 + const char *src_arr[] = { "precision mediump float; ", src }; 27.78 +#endif 27.79 + 27.80 + // keep a copy of the source code 27.81 + this->src = std::string(src); 27.82 + 27.83 + if(!sdr) { 27.84 + sdr = glCreateShader(type); 27.85 + } 27.86 + 27.87 + info_log("compiling shader: %s... ", name.c_str()); 27.88 + 27.89 + glShaderSource(sdr, sizeof src_arr / sizeof *src_arr, src_arr, 0); 27.90 + glCompileShader(sdr); 27.91 + 27.92 + int status; 27.93 + glGetShaderiv(sdr, GL_COMPILE_STATUS, &status); 27.94 + 27.95 + info_log(status ? "success\n" : "failed\n"); 27.96 + 27.97 + int info_len; 27.98 + glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len); 27.99 + if(info_len > 1) { 27.100 + char *buf = (char*)alloca(info_len); 27.101 + glGetShaderInfoLog(sdr, info_len, 0, buf); 27.102 + buf[info_len - 1] = 0; 27.103 + 27.104 + if(status) { 27.105 + info_log("%s\n", buf); 27.106 + } else { 27.107 + error_log("%s\n", buf); 27.108 + } 27.109 + } 27.110 + 27.111 + return status == GL_TRUE; 27.112 +} 27.113 + 27.114 +void Shader::destroy() 27.115 +{ 27.116 + if(sdr) { 27.117 + glDeleteShader(sdr); 27.118 + } 27.119 + sdr = type = 0; 27.120 + 27.121 + src.clear(); 27.122 + name.clear(); 27.123 +} 27.124 + 27.125 +static std::string read_source(const char *fname) 27.126 +{ 27.127 + FILE *fp; 27.128 + 27.129 + if(!(fp = fopen(fname, "rb"))) { 27.130 + error_log("failed to load shader: %s: %s\n", fname, strerror(errno)); 27.131 + return std::string(); 27.132 + } 27.133 + 27.134 + fseek(fp, 0, SEEK_END); 27.135 + long sz = ftell(fp); 27.136 + rewind(fp); 27.137 + 27.138 + char *src = (char*)alloca(sz + 1); 27.139 + if(fread(src, 1, sz, fp) < (size_t)sz) { 27.140 + error_log("failed to load shader: %s: %s\n", fname, strerror(errno)); 27.141 + fclose(fp); 27.142 + delete [] src; 27.143 + return std::string(); 27.144 + } 27.145 + src[sz] = 0; 27.146 + fclose(fp); 27.147 + 27.148 + return std::string(src); 27.149 +} 27.150 + 27.151 +bool Shader::load(const char *fname, unsigned int type) 27.152 +{ 27.153 + std::string src = read_source(fname); 27.154 + if(src.empty()) { 27.155 + return false; 27.156 + } 27.157 + set_name(fname); 27.158 + return create(src.c_str(), type); 27.159 +} 27.160 + 27.161 +// ---- shader program ---- 27.162 +ShaderProg::ShaderProg() 27.163 +{ 27.164 + prog = 0; 27.165 + must_link = true; 27.166 +} 27.167 + 27.168 +ShaderProg::~ShaderProg() 27.169 +{ 27.170 + destroy(); 27.171 +} 27.172 + 27.173 +unsigned int ShaderProg::get_id() const 27.174 +{ 27.175 + return prog; 27.176 +} 27.177 + 27.178 +bool ShaderProg::create(const char *src, unsigned int type, ...) 27.179 +{ 27.180 + va_list ap; 27.181 + 27.182 + va_start(ap, type); 27.183 + bool res = create(src, type, ap); 27.184 + va_end(ap); 27.185 + 27.186 + return res; 27.187 +} 27.188 + 27.189 +bool ShaderProg::create(const char *src, unsigned int type, va_list ap) 27.190 +{ 27.191 + destroy(); 27.192 + prog = glCreateProgram(); 27.193 + 27.194 + while(src) { 27.195 + Shader *sdr = new Shader; 27.196 + if(!sdr->create(src, type)) { 27.197 + va_end(ap); 27.198 + return false; 27.199 + } 27.200 + add_shader(sdr); 27.201 + src = va_arg(ap, const char*); 27.202 + type = va_arg(ap, unsigned int); 27.203 + } 27.204 + 27.205 + return link(); 27.206 +} 27.207 + 27.208 +bool ShaderProg::create(const char *vsrc, const char *psrc) 27.209 +{ 27.210 + return create(VSDR(vsrc), PSDR(psrc), 0); 27.211 +} 27.212 + 27.213 +bool ShaderProg::create(Shader *sdr, ...) 27.214 +{ 27.215 + va_list ap; 27.216 + 27.217 + va_start(ap, sdr); 27.218 + bool res = create(sdr, ap); 27.219 + va_end(ap); 27.220 + 27.221 + return res; 27.222 +} 27.223 + 27.224 +bool ShaderProg::create(Shader *sdr, va_list ap) 27.225 +{ 27.226 + destroy(); 27.227 + prog = glCreateProgram(); 27.228 + 27.229 + while(sdr) { 27.230 + add_shader(sdr); 27.231 + sdr = va_arg(ap, Shader*); 27.232 + } 27.233 + return link(); 27.234 +} 27.235 + 27.236 +bool ShaderProg::create(Shader *vsdr, Shader *psdr) 27.237 +{ 27.238 + return create(vsdr, psdr, 0); 27.239 +} 27.240 + 27.241 +void ShaderProg::destroy() 27.242 +{ 27.243 + if(prog) { 27.244 + glDeleteProgram(prog); 27.245 + } 27.246 + prog = 0; 27.247 + 27.248 + shaders.clear(); 27.249 + // don't actually destroy the shaders, let the ShaderSet own them 27.250 +} 27.251 + 27.252 +bool ShaderProg::load(const char *fname, unsigned int type, ...) 27.253 +{ 27.254 + va_list ap; 27.255 + va_start(ap, type); 27.256 + bool res = load(fname, type, ap); 27.257 + va_end(ap); 27.258 + 27.259 + return res; 27.260 +} 27.261 + 27.262 +bool ShaderProg::load(const char *fname, unsigned int type, va_list ap) 27.263 +{ 27.264 + destroy(); 27.265 + prog = glCreateProgram(); 27.266 + 27.267 + while(fname) { 27.268 + Shader *sdr = new Shader; 27.269 + if(!sdr->load(fname, type)) { 27.270 + delete sdr; 27.271 + return false; 27.272 + } 27.273 + add_shader(sdr); 27.274 + 27.275 + if((fname = va_arg(ap, const char*))) { 27.276 + type = va_arg(ap, unsigned int); 27.277 + } 27.278 + } 27.279 + 27.280 + return link(); 27.281 +} 27.282 + 27.283 +bool ShaderProg::load(const char *vfname, const char *pfname) 27.284 +{ 27.285 + return load(VSDR(vfname), PSDR(pfname), 0); 27.286 +} 27.287 + 27.288 +void ShaderProg::add_shader(Shader *sdr) 27.289 +{ 27.290 + glAttachShader(prog, sdr->get_id()); 27.291 +} 27.292 + 27.293 +bool ShaderProg::link() const 27.294 +{ 27.295 + bind_standard_attr(this); 27.296 + 27.297 + CHECKGLERR; 27.298 + info_log("linking program ... "); 27.299 + glLinkProgram(prog); 27.300 + 27.301 + int status; 27.302 + glGetProgramiv(prog, GL_LINK_STATUS, &status); 27.303 + 27.304 + info_log(status ? "success\n" : "failed\n"); 27.305 + 27.306 + int info_len; 27.307 + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len); 27.308 + if(info_len > 1) { 27.309 + char *buf = (char*)alloca(info_len); 27.310 + glGetProgramInfoLog(prog, info_len, 0, buf); 27.311 + buf[info_len - 1] = 0; 27.312 + 27.313 + if(status) { 27.314 + info_log("%s\n", buf); 27.315 + } else { 27.316 + error_log("%s\n", buf); 27.317 + } 27.318 + } 27.319 + 27.320 + if(status) { 27.321 + must_link = false; 27.322 + cache_state_uniforms(); 27.323 + return true; 27.324 + } 27.325 + return false; 27.326 +} 27.327 + 27.328 +void ShaderProg::bind() const 27.329 +{ 27.330 + CHECKGLERR; 27.331 + if(must_link) { 27.332 + if(!link()) { 27.333 + return; 27.334 + } 27.335 + } 27.336 + CHECKGLERR; 27.337 + glUseProgram(prog); 27.338 + ShaderProg::current = (ShaderProg*)this; 27.339 + 27.340 + setup_state_uniforms(); 27.341 +} 27.342 + 27.343 + 27.344 +int ShaderProg::get_attrib_location(const char *name) const 27.345 +{ 27.346 + glUseProgram(prog); 27.347 + return glGetAttribLocation(prog, name); 27.348 +} 27.349 + 27.350 +void ShaderProg::set_attrib_location(const char *name, int loc) const 27.351 +{ 27.352 + glBindAttribLocation(prog, loc, name); 27.353 + must_link = true; 27.354 +} 27.355 + 27.356 +int ShaderProg::get_uniform_location(const char *name) const 27.357 +{ 27.358 + glUseProgram(prog); 27.359 + return glGetUniformLocation(prog, name); 27.360 +} 27.361 + 27.362 +bool ShaderProg::set_uniform(int loc, int val) const 27.363 +{ 27.364 + glUseProgram(prog); 27.365 + if(loc >= 0) { 27.366 + glUniform1i(loc, val); 27.367 + return true; 27.368 + } 27.369 + return false; 27.370 +} 27.371 + 27.372 +bool ShaderProg::set_uniform(int loc, float val) const 27.373 +{ 27.374 + glUseProgram(prog); 27.375 + if(loc >= 0) { 27.376 + glUniform1f(loc, val); 27.377 + return true; 27.378 + } 27.379 + return false; 27.380 +} 27.381 + 27.382 +bool ShaderProg::set_uniform(int loc, const Vector2 &v) const 27.383 +{ 27.384 + glUseProgram(prog); 27.385 + if(loc >= 0) { 27.386 + glUniform2f(loc, v.x, v.y); 27.387 + return true; 27.388 + } 27.389 + return false; 27.390 +} 27.391 + 27.392 +bool ShaderProg::set_uniform(int loc, const Vector3 &v) const 27.393 +{ 27.394 + glUseProgram(prog); 27.395 + if(loc >= 0) { 27.396 + glUniform3f(loc, v.x, v.y, v.z); 27.397 + return true; 27.398 + } 27.399 + return false; 27.400 +} 27.401 + 27.402 +bool ShaderProg::set_uniform(int loc, const Vector4 &v) const 27.403 +{ 27.404 + glUseProgram(prog); 27.405 + if(loc >= 0) { 27.406 + glUniform4f(loc, v.x, v.y, v.z, v.w); 27.407 + return true; 27.408 + } 27.409 + return false; 27.410 +} 27.411 + 27.412 +bool ShaderProg::set_uniform(int loc, const Matrix3x3 &m) const 27.413 +{ 27.414 + glUseProgram(prog); 27.415 + if(loc >= 0) { 27.416 + glUniformMatrix3fv(loc, 1, GL_TRUE, m[0]); 27.417 + return true; 27.418 + } 27.419 + return false; 27.420 +} 27.421 + 27.422 +bool ShaderProg::set_uniform(int loc, const Matrix4x4 &m) const 27.423 +{ 27.424 + glUseProgram(prog); 27.425 + if(loc >= 0) { 27.426 + glUniformMatrix4fv(loc, 1, GL_TRUE, m[0]); 27.427 + return true; 27.428 + } 27.429 + return false; 27.430 +} 27.431 + 27.432 + 27.433 +bool ShaderProg::set_uniform(const char *name, int val) const 27.434 +{ 27.435 + return set_uniform(get_uniform_location(name), val); 27.436 +} 27.437 + 27.438 +bool ShaderProg::set_uniform(const char *name, float val) const 27.439 +{ 27.440 + return set_uniform(get_uniform_location(name), val); 27.441 +} 27.442 + 27.443 +bool ShaderProg::set_uniform(const char *name, const Vector2 &v) const 27.444 +{ 27.445 + return set_uniform(get_uniform_location(name), v); 27.446 +} 27.447 + 27.448 +bool ShaderProg::set_uniform(const char *name, const Vector3 &v) const 27.449 +{ 27.450 + return set_uniform(get_uniform_location(name), v); 27.451 +} 27.452 + 27.453 +bool ShaderProg::set_uniform(const char *name, const Vector4 &v) const 27.454 +{ 27.455 + return set_uniform(get_uniform_location(name), v); 27.456 +} 27.457 + 27.458 +bool ShaderProg::set_uniform(const char *name, const Matrix3x3 &m) const 27.459 +{ 27.460 + return set_uniform(get_uniform_location(name), m); 27.461 +} 27.462 + 27.463 +bool ShaderProg::set_uniform(const char *name, const Matrix4x4 &m) const 27.464 +{ 27.465 + return set_uniform(get_uniform_location(name), m); 27.466 +} 27.467 + 27.468 +static StType unist_type(GLenum type) 27.469 +{ 27.470 + switch(type) { 27.471 + case GL_FLOAT: 27.472 + return ST_FLOAT; 27.473 + case GL_FLOAT_VEC2: 27.474 + return ST_FLOAT2; 27.475 + case GL_FLOAT_VEC3: 27.476 + return ST_FLOAT3; 27.477 + case GL_FLOAT_VEC4: 27.478 + return ST_FLOAT4; 27.479 + case GL_INT: 27.480 + case GL_SAMPLER_2D: 27.481 + case GL_SAMPLER_CUBE: 27.482 +#if !GL_ES_VERSION_2_0 27.483 + case GL_SAMPLER_1D: 27.484 + case GL_SAMPLER_3D: 27.485 + case GL_SAMPLER_1D_SHADOW: 27.486 + case GL_SAMPLER_2D_SHADOW: 27.487 +#endif 27.488 + return ST_INT; 27.489 + case GL_INT_VEC2: 27.490 + return ST_INT2; 27.491 + case GL_INT_VEC3: 27.492 + return ST_INT3; 27.493 + case GL_INT_VEC4: 27.494 + return ST_INT4; 27.495 + case GL_FLOAT_MAT3: 27.496 + return ST_MATRIX3; 27.497 + case GL_FLOAT_MAT4: 27.498 + return ST_MATRIX4; 27.499 + default: 27.500 + break; 27.501 + } 27.502 + return ST_UNKNOWN; 27.503 +} 27.504 + 27.505 +void ShaderProg::cache_state_uniforms() const 27.506 +{ 27.507 + if(!glIsProgram(prog)) { 27.508 + return; 27.509 + } 27.510 + 27.511 + int num_uni; 27.512 + glGetProgramiv(prog, GL_ACTIVE_UNIFORMS, &num_uni); 27.513 + 27.514 + char name[256]; 27.515 + for(int i=0; i<num_uni; i++) { 27.516 + GLint sz; 27.517 + GLenum type; 27.518 + glGetActiveUniform(prog, i, sizeof name - 1, 0, &sz, &type, name); 27.519 + 27.520 + if(strstr(name, "st_") == name) { 27.521 + StateLocCache s; 27.522 + s.sidx = add_unistate(name, unist_type(type)); 27.523 + s.loc = glGetUniformLocation(prog, name); 27.524 + stloc_cache.push_back(s); 27.525 + } 27.526 + } 27.527 +} 27.528 + 27.529 +void ShaderProg::setup_state_uniforms() const 27.530 +{ 27.531 + for(size_t i=0; i<stloc_cache.size(); i++) { 27.532 + setup_unistate(stloc_cache[i].sidx, this, stloc_cache[i].loc); 27.533 + CHECKGLERR; 27.534 + } 27.535 +} 27.536 + 27.537 + 27.538 +// ---- ShaderSet ---- 27.539 +static Shader *load_shader(const char *fname, unsigned int type) 27.540 +{ 27.541 + Shader *sdr = new Shader; 27.542 + if(!sdr->load(fname, type)) { 27.543 + delete sdr; 27.544 + return 0; 27.545 + } 27.546 + return sdr; 27.547 +} 27.548 + 27.549 +static Shader *load_vertex_shader(const char *fname) 27.550 +{ 27.551 + return load_shader(fname, GL_VERTEX_SHADER); 27.552 +} 27.553 + 27.554 +static Shader *load_pixel_shader(const char *fname) 27.555 +{ 27.556 + return load_shader(fname, GL_FRAGMENT_SHADER); 27.557 +} 27.558 + 27.559 +#ifdef HAVE_GEOMETRY_SHADER 27.560 +static Shader *load_geom_shader(const char *fname) 27.561 +{ 27.562 + return load_shader(fname, GL_GEOMETRY_SHADER); 27.563 +} 27.564 +#endif 27.565 + 27.566 +#ifdef HAVE_TESSELATION_SHADER 27.567 +static Shader *load_tc_shader(const char *fname) 27.568 +{ 27.569 + return load_shader(fname, GL_TESS_CONTROL_SHADER); 27.570 +} 27.571 + 27.572 +static Shader *load_te_shader(const char *fname) 27.573 +{ 27.574 + return load_shader(fname, GL_TESS_EVALUATION_SHADER); 27.575 +} 27.576 +#endif 27.577 + 27.578 +static void destroy_shader(Shader *sdr) 27.579 +{ 27.580 + delete sdr; 27.581 +} 27.582 + 27.583 +ShaderSet::ShaderSet(unsigned int type) 27.584 + : DataSet<Shader*>(0, destroy_shader) 27.585 +{ 27.586 + this->type = type; 27.587 + 27.588 + switch(type) { 27.589 + case GL_VERTEX_SHADER: 27.590 + load = load_vertex_shader; 27.591 + break; 27.592 + 27.593 + case GL_FRAGMENT_SHADER: 27.594 + load = load_pixel_shader; 27.595 + break; 27.596 + 27.597 +#ifdef HAVE_GEOMETRY_SHADER 27.598 + case GL_GEOMETRY_SHADER: 27.599 + load = load_geom_shader; 27.600 + break; 27.601 +#endif 27.602 + 27.603 +#ifdef HAVE_TESSELATION_SHADER 27.604 + case GL_TESS_CONTROL_SHADER: 27.605 + load = load_tc_shader; 27.606 + break; 27.607 + 27.608 + case GL_TESS_EVALUATION_SHADER: 27.609 + load = load_te_shader; 27.610 + break; 27.611 +#endif 27.612 + 27.613 + default: 27.614 + error_log("ShaderSet constructed with invalid shader type!\n"); 27.615 + } 27.616 +} 27.617 + 27.618 +static struct { const char *name; int loc; } attr_loc[] = { 27.619 + {"attr_vertex", MESH_ATTR_VERTEX}, 27.620 + {"attr_normal", MESH_ATTR_NORMAL}, 27.621 + {"attr_tangent", MESH_ATTR_TANGENT}, 27.622 + {"attr_texcoord", MESH_ATTR_TEXCOORD}, 27.623 + {"attr_color", MESH_ATTR_COLOR}, 27.624 + {"attr_boneweights", MESH_ATTR_BONEWEIGHTS}, 27.625 + {"attr_boneidx", MESH_ATTR_BONEIDX} 27.626 +}; 27.627 + 27.628 +static void bind_standard_attr(const ShaderProg *prog) 27.629 +{ 27.630 + // we must link once to find out which are the active attributes 27.631 + glLinkProgram(prog->get_id()); 27.632 + 27.633 + int num_attr; 27.634 + glGetProgramiv(prog->get_id(), GL_ACTIVE_ATTRIBUTES, &num_attr); 27.635 + 27.636 + char name[256]; 27.637 + for(int i=0; i<num_attr; i++) { 27.638 + GLint sz; 27.639 + GLenum type; 27.640 + glGetActiveAttrib(prog->get_id(), i, sizeof name - 1, 0, &sz, &type, name); 27.641 + 27.642 + for(int j=0; j<(int)(sizeof attr_loc / sizeof *attr_loc); j++) { 27.643 + if(strcmp(name, attr_loc[j].name) == 0) { 27.644 + prog->set_attrib_location(name, attr_loc[j].loc); 27.645 + } 27.646 + } 27.647 + } 27.648 +} 27.649 + 27.650 + 27.651 +/* 27.652 +static const char *strtype(unsigned int type) 27.653 +{ 27.654 + switch(type) { 27.655 + case GL_VERTEX_SHADER: 27.656 + return "vertex"; 27.657 + case GL_FRAGMENT_SHADER: 27.658 + return "fragment"; 27.659 +#ifdef HAVE_GEOMETRY_SHADER 27.660 + case GL_GEOMETRY_SHADER: 27.661 + return "geometry"; 27.662 +#endif 27.663 +#ifdef HAVE_TESSELATION_SHADER 27.664 + case GL_TESS_CONTROL_SHADER: 27.665 + return "tesselation control"; 27.666 + case GL_TESS_EVALUATION_SHADER: 27.667 + return "tesselation evaluation"; 27.668 +#endif 27.669 + default: 27.670 + break; 27.671 + } 27.672 + return "<unknown>"; 27.673 +} 27.674 +*/
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 28.2 +++ b/src/shader.h Sun Aug 24 09:41:24 2014 +0300 28.3 @@ -0,0 +1,150 @@ 28.4 +#ifndef SHADER_H_ 28.5 +#define SHADER_H_ 28.6 + 28.7 +#include <vector> 28.8 +#include <string> 28.9 +#include "vmath/vmath.h" 28.10 +#include "opengl.h" 28.11 +#include "dataset.h" 28.12 + 28.13 +class ShaderProg; 28.14 + 28.15 + 28.16 +void bind_shader(const ShaderProg *sdr); 28.17 +const ShaderProg *get_current_shader(); 28.18 + 28.19 + 28.20 +class Shader { 28.21 +private: 28.22 + unsigned int sdr; 28.23 + unsigned int type; 28.24 + std::string name, src; 28.25 + 28.26 +public: 28.27 + Shader(); 28.28 + ~Shader(); 28.29 + 28.30 + unsigned int get_id() const; 28.31 + 28.32 + void set_name(const char *name); 28.33 + const char *get_name() const; 28.34 + 28.35 + bool create(const char *src, unsigned int type); 28.36 + void destroy(); 28.37 + 28.38 + bool load(const char *fname, unsigned int type); 28.39 + 28.40 + 28.41 + // these functions are only meant to be used by the ShaderSet 28.42 + static Shader *create_shader(); 28.43 + static bool load_shader(Shader *sdr, const char *fname); 28.44 + static bool done_shader(Shader *sdr, unsigned int type); 28.45 + static void destroy_shader(Shader *sdr); 28.46 +}; 28.47 + 28.48 +#define VSDR(s) s, GL_VERTEX_SHADER 28.49 +#define FSDR(s) s, GL_FRAGMENT_SHADER 28.50 +#define PSDR(s) FSDR(s) 28.51 +#define GSDR(s) s, GL_GEOMETRY_SHADER 28.52 +#define TCSDR(s) s, GL_TESS_CONTROL_SHADER 28.53 +#define TESDR(s) s, GL_TESS_EVALUATION_SHADER 28.54 + 28.55 +class ShaderProg { 28.56 +private: 28.57 + unsigned int prog; 28.58 + mutable bool must_link; 28.59 + std::vector<Shader*> shaders; 28.60 + 28.61 + struct StateLocCache { int sidx, loc; }; 28.62 + /** a cache of all st_ prefixed uniform locations and their corresponding 28.63 + * index in the global uniform state vector (see unistate.h) 28.64 + */ 28.65 + mutable std::vector<StateLocCache> stloc_cache; 28.66 + 28.67 + void cache_state_uniforms() const; 28.68 + void setup_state_uniforms() const; 28.69 + 28.70 +public: 28.71 + static ShaderProg *current; 28.72 + 28.73 + ShaderProg(); 28.74 + ~ShaderProg(); 28.75 + 28.76 + /// returns the OpenGL object id for this shader program 28.77 + unsigned int get_id() const; 28.78 + 28.79 + /** takes a series of shaders, and constructs a program object by linking 28.80 + * them together. Terminate with a null pointer (don't use 0!) */ 28.81 + bool create(Shader *sdr, ...); 28.82 + /// same as above, but with a va_list instead of variable arguments. 28.83 + bool create(Shader *sdr, va_list ap); 28.84 + /** takes two shaders (vertex and pixel) and constructs a program object by 28.85 + * linking them together. Either one can be null. */ 28.86 + bool create(Shader *vsdr, Shader *psdr); 28.87 + 28.88 + /** takes a series of shader source/shader type pairs and constructs a program 28.89 + * object by linking them together. Terminate with a null pointer (don't use 0!) 28.90 + * You can use the VSDR, PSDR, GSDR, TCSDR, TESDR convenience macros for passing 28.91 + * the pairs. 28.92 + * Example: create(VSDR(vsrc0), VSDR(vsrc1), PSDR(psrc), NULL); 28.93 + */ 28.94 + bool create(const char *src, unsigned int type, ...); 28.95 + /// same as above, but with a va_list instead of variable arguments. 28.96 + bool create(const char *src, unsigned int type, va_list ap); 28.97 + /** takes two shaders source strings (vertex and pixel) and constructs 28.98 + * a program object by linking them together. Either one can be null. */ 28.99 + bool create(const char *vsrc, const char *psrc); 28.100 + 28.101 + void destroy(); 28.102 + 28.103 + /** takes a series of shader filename/shader type pairs, loads the shaders and 28.104 + * constructs a program object by linking them together. Terminate with a null 28.105 + * pointer (don't use 0!). You can use the VSDR, PSDR, GSDR, TCSDR, TESDR convenience 28.106 + * macros for passing the pairs. 28.107 + * Example: load(VSDR("vsdr1.glsl"), VSDR("vsdr2.glsl"), PSDR("pixel.glsl"), NULL); 28.108 + */ 28.109 + bool load(const char *fname, unsigned int type, ...); 28.110 + /// same as above, but with a va_list instead of variable arguments. 28.111 + bool load(const char *fname, unsigned int type, va_list ap); 28.112 + /** takes the filenames of two shader files (vertex and pixel), loads them and 28.113 + * constructs a program object by linking them together. Either one can be null */ 28.114 + bool load(const char *vsrc, const char *psrc); 28.115 + 28.116 + void add_shader(Shader *sdr); 28.117 + bool link() const; 28.118 + 28.119 + void bind() const; 28.120 + 28.121 + int get_attrib_location(const char *name) const; 28.122 + void set_attrib_location(const char *name, int loc) const; 28.123 + 28.124 + int get_uniform_location(const char *name) const; 28.125 + 28.126 + bool set_uniform(int loc, int val) const; 28.127 + bool set_uniform(int loc, float val) const; 28.128 + bool set_uniform(int loc, const Vector2 &v) const; 28.129 + bool set_uniform(int loc, const Vector3 &v) const; 28.130 + bool set_uniform(int loc, const Vector4 &v) const; 28.131 + bool set_uniform(int loc, const Matrix3x3 &m) const; 28.132 + bool set_uniform(int loc, const Matrix4x4 &m) const; 28.133 + 28.134 + bool set_uniform(const char *name, int val) const; 28.135 + bool set_uniform(const char *name, float val) const; 28.136 + bool set_uniform(const char *name, const Vector2 &v) const; 28.137 + bool set_uniform(const char *name, const Vector3 &v) const; 28.138 + bool set_uniform(const char *name, const Vector4 &v) const; 28.139 + bool set_uniform(const char *name, const Matrix3x3 &m) const; 28.140 + bool set_uniform(const char *name, const Matrix4x4 &m) const; 28.141 + 28.142 + friend void setup_unistate(const ShaderProg*); 28.143 +}; 28.144 + 28.145 +class ShaderSet : public DataSet<Shader*> { 28.146 +private: 28.147 + unsigned int type; 28.148 + 28.149 +public: 28.150 + ShaderSet(unsigned int type); 28.151 +}; 28.152 + 28.153 +#endif // SHADER_H_
29.1 --- a/src/texture.cc Sat Aug 23 12:03:29 2014 +0300 29.2 +++ b/src/texture.cc Sun Aug 24 09:41:24 2014 +0300 29.3 @@ -64,18 +64,16 @@ 29.4 return img; 29.5 } 29.6 29.7 +unsigned int Texture::get_type() const 29.8 +{ 29.9 + return type; 29.10 +} 29.11 + 29.12 unsigned int Texture::get_texture_id() const 29.13 { 29.14 return tex; 29.15 } 29.16 29.17 -void Texture::bind(int tunit) const 29.18 -{ 29.19 - glActiveTextureARB(GL_TEXTURE0_ARB + tunit); 29.20 - glBindTexture(type, tex); 29.21 - glActiveTextureARB(GL_TEXTURE0_ARB); 29.22 -} 29.23 - 29.24 bool Texture::load(const char *fname) 29.25 { 29.26 Image image; 29.27 @@ -86,6 +84,26 @@ 29.28 return true; 29.29 } 29.30 29.31 +void bind_texture(const Texture *tex, int tunit) 29.32 +{ 29.33 + static unsigned int cur_tex_type[8] = { 29.34 + GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, 29.35 + GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D 29.36 + }; 29.37 + 29.38 + glActiveTextureARB(GL_TEXTURE0_ARB + tunit); 29.39 + if(tex) { 29.40 + glBindTexture(tex->get_type(), tex->get_texture_id()); 29.41 + glEnable(tex->get_type()); 29.42 + } else { 29.43 + glDisable(cur_tex_type[tunit]); 29.44 + } 29.45 + glActiveTextureARB(GL_TEXTURE0_ARB); 29.46 + 29.47 + cur_tex_type[tunit] = tex->get_type(); 29.48 +} 29.49 + 29.50 + 29.51 unsigned int next_pow2(unsigned int x) 29.52 { 29.53 x -= 1;
30.1 --- a/src/texture.h Sat Aug 23 12:03:29 2014 +0300 30.2 +++ b/src/texture.h Sun Aug 24 09:41:24 2014 +0300 30.3 @@ -23,12 +23,14 @@ 30.4 Image &get_image(); 30.5 const Image &get_image() const; 30.6 30.7 + unsigned int get_type() const; 30.8 unsigned int get_texture_id() const; 30.9 - void bind(int tunit = 0) const; 30.10 30.11 bool load(const char *fname); 30.12 }; 30.13 30.14 +void bind_texture(const Texture *tex, int unit = 0); 30.15 + 30.16 unsigned int next_pow2(unsigned int x); 30.17 30.18 #endif // TEXTURE_H_
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 31.2 +++ b/src/unistate.cc Sun Aug 24 09:41:24 2014 +0300 31.3 @@ -0,0 +1,678 @@ 31.4 +#include <map> 31.5 +#include <vector> 31.6 +#include "unistate.h" 31.7 +#include "shader.h" 31.8 +#include "logger.h" 31.9 + 31.10 +struct StateItem { 31.11 + StType type; 31.12 + 31.13 + union { 31.14 + int ival[4]; 31.15 + float fval[16]; 31.16 + }; 31.17 + int transpose; // for matrices 31.18 +}; 31.19 + 31.20 +static const char *typestr(StType type); 31.21 +static int type_nelem(StType type); 31.22 +static StType float_type(int elem); 31.23 +static StType int_type(int elem); 31.24 + 31.25 +std::vector<StateItem> state; 31.26 +std::map<std::string, int> stateidx; 31.27 + 31.28 + 31.29 +int add_unistate(const char *name, StType type) 31.30 +{ 31.31 + static const float ident3[] = {1, 0, 0, 0, 1, 0, 0, 0, 1}; 31.32 + static const float ident4[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; 31.33 + 31.34 + if(stateidx.find(name) != stateidx.end()) { 31.35 + return stateidx[name]; 31.36 + } 31.37 + 31.38 + StateItem sitem; 31.39 + memset(&sitem, 0, sizeof sitem); 31.40 + sitem.type = type; 31.41 + 31.42 + // initialize to a reasonable default value 31.43 + switch(type) { 31.44 + case ST_MATRIX3: 31.45 + memcpy(sitem.fval, ident3, sizeof ident3); 31.46 + break; 31.47 + 31.48 + case ST_MATRIX4: 31.49 + memcpy(sitem.fval, ident4, sizeof ident4); 31.50 + break; 31.51 + 31.52 + default: 31.53 + break; // in all other cases leave it zero (see memset above) 31.54 + } 31.55 + 31.56 + int sidx = state.size(); 31.57 + state.push_back(sitem); 31.58 + stateidx[name] = sidx; 31.59 + 31.60 + debug_log("adding uniform state [%d]: %s %s\n", sidx, typestr(sitem.type), name); 31.61 + 31.62 + return sidx; 31.63 +} 31.64 + 31.65 +int get_unistate_index(const char *name) 31.66 +{ 31.67 + std::map<std::string, int>::const_iterator it = stateidx.find(name); 31.68 + if(it != stateidx.end()) { 31.69 + return it->second; 31.70 + } 31.71 + return -1; 31.72 +} 31.73 + 31.74 +#define CHECK_INDEX(i) \ 31.75 + if(i < 0 || i >= (int)state.size()) return 31.76 + 31.77 +#define CHECK_COUNT(count, type) \ 31.78 + do { \ 31.79 + int max_elem = type_nelem(type); \ 31.80 + if(!(count) || (count) > max_elem) { \ 31.81 + count = max_elem; \ 31.82 + } \ 31.83 + } while(0) 31.84 + 31.85 +void set_unistate(int sidx, const int *val, int count) 31.86 +{ 31.87 + CHECK_INDEX(sidx); 31.88 + CHECK_COUNT(count, state[sidx].type); 31.89 + 31.90 + memcpy(state[sidx].ival, val, count * sizeof *state[sidx].ival); 31.91 +} 31.92 + 31.93 +void set_unistate(int sidx, const float *val, int count) 31.94 +{ 31.95 + CHECK_INDEX(sidx); 31.96 + CHECK_COUNT(count, state[sidx].type); 31.97 + 31.98 + memcpy(state[sidx].fval, val, count * sizeof *state[sidx].fval); 31.99 + state[sidx].transpose = 0; 31.100 +} 31.101 + 31.102 +void get_unistate(int sidx, int *val, int count) 31.103 +{ 31.104 + CHECK_INDEX(sidx); 31.105 + CHECK_COUNT(count, state[sidx].type); 31.106 + 31.107 + memcpy(val, state[sidx].ival, count * sizeof *val); 31.108 +} 31.109 + 31.110 +void get_unistate(int sidx, float *val, int count) 31.111 +{ 31.112 + CHECK_INDEX(sidx); 31.113 + CHECK_COUNT(count, state[sidx].type); 31.114 + 31.115 + memcpy(val, state[sidx].fval, count * sizeof *val); 31.116 +} 31.117 + 31.118 +void set_unistate(int sidx, int val) 31.119 +{ 31.120 + set_unistate(sidx, &val, 1); 31.121 +} 31.122 + 31.123 +void set_unistate(int sidx, float val) 31.124 +{ 31.125 + set_unistate(sidx, &val, 1); 31.126 +} 31.127 + 31.128 +void set_unistate(int sidx, const Vector2 &vec) 31.129 +{ 31.130 + set_unistate(sidx, &vec.x, 2); 31.131 +} 31.132 + 31.133 +void set_unistate(int sidx, const Vector3 &vec) 31.134 +{ 31.135 + set_unistate(sidx, &vec.x, 3); 31.136 +} 31.137 + 31.138 +void set_unistate(int sidx, const Vector4 &vec) 31.139 +{ 31.140 + set_unistate(sidx, &vec.x, 4); 31.141 +} 31.142 + 31.143 +void set_unistate(int sidx, const Matrix3x3 &mat) 31.144 +{ 31.145 + set_unistate(sidx, mat[0], 9); 31.146 + state[sidx].transpose = 1; 31.147 +} 31.148 + 31.149 +void set_unistate(int sidx, const Matrix4x4 &mat) 31.150 +{ 31.151 + set_unistate(sidx, mat[0], 16); 31.152 + state[sidx].transpose = 1; 31.153 +} 31.154 + 31.155 + 31.156 +int set_unistate(const char *name, int *val, int count) 31.157 +{ 31.158 + int sidx = get_unistate_index(name); 31.159 + if(sidx < 0) { 31.160 + StType type = int_type(count); 31.161 + if(type == ST_UNKNOWN) { 31.162 + error_log("invalid element count (%d) while setting previously unknown unistate item \"%s\"\n", 31.163 + count, name); 31.164 + return -1; 31.165 + } 31.166 + 31.167 + sidx = add_unistate(name, type); 31.168 + } 31.169 + set_unistate(sidx, val); 31.170 + return sidx; 31.171 +} 31.172 + 31.173 +int set_unistate(const char *name, float *val, int count) 31.174 +{ 31.175 + int sidx = get_unistate_index(name); 31.176 + if(sidx < 0) { 31.177 + StType type = float_type(count); 31.178 + if(type == ST_UNKNOWN) { 31.179 + error_log("invalid element count (%d) while setting previously unknown unistate item \"%s\"\n", 31.180 + count, name); 31.181 + return -1; 31.182 + } 31.183 + 31.184 + sidx = add_unistate(name, type); 31.185 + } 31.186 + set_unistate(sidx, val); 31.187 + return sidx; 31.188 +} 31.189 + 31.190 +int set_unistate(const char *name, int val) 31.191 +{ 31.192 + int sidx = get_unistate_index(name); 31.193 + if(sidx < 0) { 31.194 + sidx = add_unistate(name, ST_INT); 31.195 + } 31.196 + set_unistate(sidx, val); 31.197 + return sidx; 31.198 +} 31.199 + 31.200 +int set_unistate(const char *name, float val) 31.201 +{ 31.202 + int sidx = get_unistate_index(name); 31.203 + if(sidx < 0) { 31.204 + sidx = add_unistate(name, ST_FLOAT); 31.205 + } 31.206 + set_unistate(sidx, val); 31.207 + return sidx; 31.208 +} 31.209 + 31.210 +int set_unistate(const char *name, const Vector2 &vec) 31.211 +{ 31.212 + int sidx = get_unistate_index(name); 31.213 + if(sidx < 0) { 31.214 + sidx = add_unistate(name, ST_FLOAT2); 31.215 + } 31.216 + set_unistate(sidx, vec); 31.217 + return sidx; 31.218 +} 31.219 + 31.220 +int set_unistate(const char *name, const Vector3 &vec) 31.221 +{ 31.222 + int sidx = get_unistate_index(name); 31.223 + if(sidx < 0) { 31.224 + sidx = add_unistate(name, ST_FLOAT3); 31.225 + } 31.226 + set_unistate(sidx, vec); 31.227 + return sidx; 31.228 +} 31.229 + 31.230 +int set_unistate(const char *name, const Vector4 &vec) 31.231 +{ 31.232 + int sidx = get_unistate_index(name); 31.233 + if(sidx < 0) { 31.234 + sidx = add_unistate(name, ST_FLOAT4); 31.235 + } 31.236 + set_unistate(sidx, vec); 31.237 + return sidx; 31.238 +} 31.239 + 31.240 +int set_unistate(const char *name, const Matrix3x3 &mat) 31.241 +{ 31.242 + int sidx = get_unistate_index(name); 31.243 + if(sidx < 0) { 31.244 + sidx = add_unistate(name, ST_MATRIX3); 31.245 + } 31.246 + set_unistate(sidx, mat); 31.247 + return sidx; 31.248 +} 31.249 + 31.250 +int set_unistate(const char *name, const Matrix4x4 &mat) 31.251 +{ 31.252 + int sidx = get_unistate_index(name); 31.253 + if(sidx < 0) { 31.254 + sidx = add_unistate(name, ST_MATRIX4); 31.255 + } 31.256 + set_unistate(sidx, mat); 31.257 + return sidx; 31.258 +} 31.259 + 31.260 + 31.261 +int get_unistate_int(int sidx) 31.262 +{ 31.263 + int val = 0; 31.264 + get_unistate(sidx, &val, 1); 31.265 + return val; 31.266 +} 31.267 + 31.268 +float get_unistate_float(int sidx) 31.269 +{ 31.270 + float val = 0.0f; 31.271 + get_unistate(sidx, &val, 1); 31.272 + return val; 31.273 +} 31.274 + 31.275 +Vector2 get_unistate_vec2(int sidx) 31.276 +{ 31.277 + float val[2] = {0.0f, 0.0f}; 31.278 + get_unistate(sidx, val, 2); 31.279 + return Vector2(val[0], val[1]); 31.280 +} 31.281 + 31.282 +Vector3 get_unistate_vec3(int sidx) 31.283 +{ 31.284 + float val[3] = {0.0f, 0.0f, 0.0f}; 31.285 + get_unistate(sidx, val, 3); 31.286 + return Vector3(val[0], val[1], val[2]); 31.287 +} 31.288 + 31.289 +Vector4 get_unistate_vec4(int sidx) 31.290 +{ 31.291 + float val[4] = {0.0f, 0.0f, 0.0f}; 31.292 + get_unistate(sidx, val, 4); 31.293 + return Vector4(val[0], val[1], val[2], val[3]); 31.294 +} 31.295 + 31.296 +Matrix3x3 get_unistate_mat3(int sidx) 31.297 +{ 31.298 + Matrix3x3 res; 31.299 + get_unistate(sidx, res.m[0], 9); 31.300 + return res; 31.301 +} 31.302 + 31.303 +Matrix4x4 get_unistate_mat4(int sidx) 31.304 +{ 31.305 + Matrix4x4 res; 31.306 + get_unistate(sidx, res.m[0], 16); 31.307 + return res; 31.308 +} 31.309 + 31.310 + 31.311 +int get_unistate_int(const char *name) 31.312 +{ 31.313 + int sidx = get_unistate_index(name); 31.314 + if(sidx == -1) { 31.315 + return 0; 31.316 + } 31.317 + return get_unistate_int(sidx); 31.318 +} 31.319 + 31.320 +float get_unistate_float(const char *name) 31.321 +{ 31.322 + int sidx = get_unistate_index(name); 31.323 + if(sidx == -1) { 31.324 + return 0.0f; 31.325 + } 31.326 + return get_unistate_float(sidx); 31.327 +} 31.328 + 31.329 +Vector2 get_unistate_vec2(const char *name) 31.330 +{ 31.331 + int sidx = get_unistate_index(name); 31.332 + if(sidx == -1) { 31.333 + return Vector2(); 31.334 + } 31.335 + return get_unistate_vec2(sidx); 31.336 +} 31.337 + 31.338 +Vector3 get_unistate_vec3(const char *name) 31.339 +{ 31.340 + int sidx = get_unistate_index(name); 31.341 + if(sidx == -1) { 31.342 + return Vector3(); 31.343 + } 31.344 + return get_unistate_vec3(sidx); 31.345 +} 31.346 + 31.347 +Vector4 get_unistate_vec4(const char *name) 31.348 +{ 31.349 + int sidx = get_unistate_index(name); 31.350 + if(sidx == -1) { 31.351 + return Vector4(); 31.352 + } 31.353 + return get_unistate_vec4(sidx); 31.354 +} 31.355 + 31.356 +Matrix3x3 get_unistate_mat3(const char *name) 31.357 +{ 31.358 + int sidx = get_unistate_index(name); 31.359 + if(sidx == -1) { 31.360 + return Matrix3x3(); 31.361 + } 31.362 + return get_unistate_mat3(sidx); 31.363 +} 31.364 + 31.365 +Matrix4x4 get_unistate_mat4(const char *name) 31.366 +{ 31.367 + int sidx = get_unistate_index(name); 31.368 + if(sidx == -1) { 31.369 + return Matrix4x4(); 31.370 + } 31.371 + return get_unistate_mat4(sidx); 31.372 +} 31.373 + 31.374 + 31.375 +void setup_unistate(const ShaderProg *sdr) 31.376 +{ 31.377 + if(!sdr) { 31.378 + if(!(sdr = ShaderProg::current)) { 31.379 + return; 31.380 + } 31.381 + } 31.382 + 31.383 + sdr->setup_state_uniforms(); 31.384 +} 31.385 + 31.386 +bool setup_unistate(int sidx, const ShaderProg *sdr, int loc) 31.387 +{ 31.388 + if(loc < 0 || sidx < 0 || sidx >= (int)state.size()) { 31.389 + return false; 31.390 + } 31.391 + 31.392 + CHECKGLERR; 31.393 + glUseProgram(sdr->get_id()); 31.394 + CHECKGLERR; 31.395 + 31.396 + switch(state[sidx].type) { 31.397 + case ST_INT: 31.398 + glUniform1iv(loc, 1, state[sidx].ival); 31.399 + break; 31.400 + case ST_INT2: 31.401 + glUniform2iv(loc, 1, state[sidx].ival); 31.402 + break; 31.403 + case ST_INT3: 31.404 + glUniform3iv(loc, 1, state[sidx].ival); 31.405 + break; 31.406 + case ST_INT4: 31.407 + glUniform4iv(loc, 1, state[sidx].ival); 31.408 + break; 31.409 + 31.410 + case ST_FLOAT: 31.411 + glUniform1fv(loc, 1, state[sidx].fval); 31.412 + break; 31.413 + case ST_FLOAT2: 31.414 + glUniform2fv(loc, 1, state[sidx].fval); 31.415 + break; 31.416 + case ST_FLOAT3: 31.417 + glUniform3fv(loc, 1, state[sidx].fval); 31.418 + break; 31.419 + case ST_FLOAT4: 31.420 + glUniform4fv(loc, 1, state[sidx].fval); 31.421 + break; 31.422 + 31.423 + case ST_MATRIX3: 31.424 +#ifdef GL_ES_VERSION_2_0 31.425 + { 31.426 + float tmat[9], *ptr = tmat; 31.427 + for(int i=0; i<3; i++) { 31.428 + for(int j=0; j<3; j++) { 31.429 + *ptr++ = state[sidx].fval[j * 3 + i]; 31.430 + } 31.431 + } 31.432 + glUniformMatrix3fv(loc, 1, GL_FALSE, tmat); 31.433 + } 31.434 +#else 31.435 + glUniformMatrix3fv(loc, 1, state[sidx].transpose, state[sidx].fval); 31.436 +#endif 31.437 + break; 31.438 + 31.439 + case ST_MATRIX4: 31.440 +#ifdef GL_ES_VERSION_2_0 31.441 + { 31.442 + float tmat[16], *ptr = tmat; 31.443 + for(int i=0; i<4; i++) { 31.444 + for(int j=0; j<4; j++) { 31.445 + *ptr++ = state[sidx].fval[j * 4 + i]; 31.446 + } 31.447 + } 31.448 + glUniformMatrix4fv(loc, 1, GL_FALSE, tmat); 31.449 + } 31.450 +#else 31.451 + glUniformMatrix4fv(loc, 1, state[sidx].transpose, state[sidx].fval); 31.452 +#endif 31.453 + break; 31.454 + 31.455 + default: 31.456 + return false; 31.457 + } 31.458 + 31.459 + CHECKGLERR; 31.460 + return true; 31.461 +} 31.462 + 31.463 +bool setup_unistate(const char *name, const ShaderProg *sdr) 31.464 +{ 31.465 + int loc = sdr->get_uniform_location(name); 31.466 + if(loc == -1) { 31.467 + return false; 31.468 + } 31.469 + return setup_unistate(get_unistate_index(name), sdr, loc); 31.470 +} 31.471 + 31.472 +void set_world_matrix(const Matrix4x4 &mat) 31.473 +{ 31.474 + static int sidx = -1, sidx_transp, sidx_mat3; 31.475 + 31.476 + if(sidx == -1) { 31.477 + sidx = add_unistate("st_world_matrix", ST_MATRIX4); 31.478 + sidx_mat3 = add_unistate("st_world_matrix3", ST_MATRIX3); 31.479 + sidx_transp = add_unistate("st_world_matrix_transpose", ST_MATRIX4); 31.480 + } 31.481 + 31.482 + set_unistate(sidx, mat); 31.483 + set_unistate(sidx_mat3, Matrix3x3(mat)); 31.484 + set_unistate(sidx_transp, mat[0]); // by using the float* variant, we unset the transpose flag 31.485 +} 31.486 + 31.487 +void set_view_matrix(const Matrix4x4 &mat) 31.488 +{ 31.489 + static int sidx = -1, sidx_transp, sidx_mat3; 31.490 + 31.491 + if(sidx == -1) { 31.492 + sidx = add_unistate("st_view_matrix", ST_MATRIX4); 31.493 + sidx_mat3 = add_unistate("st_view_matrix3", ST_MATRIX3); 31.494 + sidx_transp = add_unistate("st_view_matrix_transpose", ST_MATRIX4); 31.495 + } 31.496 + 31.497 + set_unistate(sidx, mat); 31.498 + set_unistate(sidx_mat3, Matrix3x3(mat)); 31.499 + set_unistate(sidx_transp, mat[0]); // by using the float* variant, we unset the transpose flag 31.500 +} 31.501 + 31.502 +void set_projection_matrix(const Matrix4x4 &mat) 31.503 +{ 31.504 + static int sidx = -1; 31.505 + 31.506 + if(sidx == -1) { 31.507 + sidx = add_unistate("st_proj_matrix", ST_MATRIX4); 31.508 + } 31.509 + 31.510 + set_unistate(sidx, mat); 31.511 +} 31.512 + 31.513 +void set_texture_matrix(const Matrix4x4 &mat) 31.514 +{ 31.515 + static int sidx = -1; 31.516 + 31.517 + if(sidx == -1) { 31.518 + sidx = add_unistate("st_tex_matrix", ST_MATRIX4); 31.519 + } 31.520 + 31.521 + set_unistate(sidx, mat); 31.522 +} 31.523 + 31.524 +Matrix4x4 get_world_matrix() 31.525 +{ 31.526 + static int sidx = -1; 31.527 + 31.528 + if(sidx == -1) { 31.529 + if((sidx = get_unistate_index("st_world_matrix")) == -1) { 31.530 + return Matrix4x4(); 31.531 + } 31.532 + } 31.533 + return get_unistate_mat4(sidx); 31.534 +} 31.535 + 31.536 +Matrix4x4 get_view_matrix() 31.537 +{ 31.538 + static int sidx = -1; 31.539 + 31.540 + if(sidx == -1) { 31.541 + if((sidx = get_unistate_index("st_view_matrix")) == -1) { 31.542 + return Matrix4x4(); 31.543 + } 31.544 + } 31.545 + return get_unistate_mat4(sidx); 31.546 +} 31.547 + 31.548 +Matrix4x4 get_projection_matrix() 31.549 +{ 31.550 + static int sidx = -1; 31.551 + 31.552 + if(sidx == -1) { 31.553 + if((sidx = get_unistate_index("st_proj_matrix")) == -1) { 31.554 + return Matrix4x4(); 31.555 + } 31.556 + } 31.557 + return get_unistate_mat4(sidx); 31.558 +} 31.559 + 31.560 +Matrix4x4 get_texture_matrix() 31.561 +{ 31.562 + static int sidx = -1; 31.563 + 31.564 + if(sidx == -1) { 31.565 + if((sidx = get_unistate_index("st_tex_matrix")) == -1) { 31.566 + return Matrix4x4(); 31.567 + } 31.568 + } 31.569 + return get_unistate_mat4(sidx); 31.570 +} 31.571 + 31.572 +void setup_gl_matrices() 31.573 +{ 31.574 +#ifdef USE_OLDGL 31.575 + Matrix4x4 modelview = get_world_matrix() * get_view_matrix(); 31.576 + Matrix4x4 proj = get_projection_matrix(); 31.577 + Matrix4x4 tex = get_texture_matrix(); 31.578 + 31.579 + glMatrixMode(GL_TEXTURE); 31.580 + glLoadTransposeMatrixf(tex[0]); 31.581 + glMatrixMode(GL_PROJECTION); 31.582 + glLoadTransposeMatrixf(proj[0]); 31.583 + glMatrixMode(GL_MODELVIEW); 31.584 + glLoadTransposeMatrixf(modelview[0]); 31.585 +#endif 31.586 +} 31.587 + 31.588 +static const char *typestr(StType type) 31.589 +{ 31.590 + switch(type) { 31.591 + case ST_INT: 31.592 + return "int"; 31.593 + case ST_INT2: 31.594 + return "ivec2"; 31.595 + case ST_INT3: 31.596 + return "ivec3"; 31.597 + case ST_INT4: 31.598 + return "ivec4"; 31.599 + case ST_FLOAT: 31.600 + return "float"; 31.601 + case ST_FLOAT2: 31.602 + return "vec2"; 31.603 + case ST_FLOAT3: 31.604 + return "vec3"; 31.605 + case ST_FLOAT4: 31.606 + return "vec4"; 31.607 + case ST_MATRIX3: 31.608 + return "mat3"; 31.609 + case ST_MATRIX4: 31.610 + return "mat4"; 31.611 + 31.612 + default: 31.613 + break; 31.614 + } 31.615 + return "<unknown>"; 31.616 +} 31.617 + 31.618 +static int type_nelem(StType type) 31.619 +{ 31.620 + switch(type) { 31.621 + case ST_INT: 31.622 + case ST_FLOAT: 31.623 + return 1; 31.624 + case ST_INT2: 31.625 + case ST_FLOAT2: 31.626 + return 2; 31.627 + case ST_INT3: 31.628 + case ST_FLOAT3: 31.629 + return 3; 31.630 + case ST_INT4: 31.631 + case ST_FLOAT4: 31.632 + return 4; 31.633 + case ST_MATRIX3: 31.634 + return 9; 31.635 + case ST_MATRIX4: 31.636 + return 16; 31.637 + 31.638 + default: 31.639 + break; 31.640 + } 31.641 + 31.642 + return 0; 31.643 +} 31.644 + 31.645 +static StType float_type(int elem) 31.646 +{ 31.647 + switch(elem) { 31.648 + case 1: 31.649 + return ST_FLOAT; 31.650 + case 2: 31.651 + return ST_FLOAT2; 31.652 + case 3: 31.653 + return ST_FLOAT3; 31.654 + case 4: 31.655 + return ST_FLOAT4; 31.656 + case 9: 31.657 + return ST_MATRIX3; 31.658 + case 16: 31.659 + return ST_MATRIX4; 31.660 + default: 31.661 + break; 31.662 + } 31.663 + return ST_UNKNOWN; 31.664 +} 31.665 + 31.666 +static StType int_type(int elem) 31.667 +{ 31.668 + switch(elem) { 31.669 + case 1: 31.670 + return ST_INT; 31.671 + case 2: 31.672 + return ST_INT2; 31.673 + case 3: 31.674 + return ST_INT3; 31.675 + case 4: 31.676 + return ST_INT4; 31.677 + default: 31.678 + break; 31.679 + } 31.680 + return ST_UNKNOWN; 31.681 +}
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 32.2 +++ b/src/unistate.h Sun Aug 24 09:41:24 2014 +0300 32.3 @@ -0,0 +1,104 @@ 32.4 +#ifndef UNISTATE_H_ 32.5 +#define UNISTATE_H_ 32.6 + 32.7 +#include "vmath/vmath.h" 32.8 + 32.9 +class ShaderProg; 32.10 + 32.11 +enum StType { 32.12 + ST_UNKNOWN, 32.13 + ST_INT, ST_INT2, ST_INT3, ST_INT4, 32.14 + ST_FLOAT, ST_FLOAT2, ST_FLOAT3, ST_FLOAT4, 32.15 + ST_MATRIX3, ST_MATRIX4 32.16 +}; 32.17 + 32.18 +int add_unistate(const char *name, StType type); 32.19 +int get_unistate_index(const char *name); 32.20 + 32.21 +/** set the uniform state identified by \param sidx by copying 32.22 + * a number of elements from \param val. If \param count is 0 32.23 + * then it's automatically set based on the type of this state item. 32.24 + * @{ */ 32.25 +void set_unistate(int sidx, const int *val, int count = 0); 32.26 +void set_unistate(int sidx, const float *val, int count = 0); 32.27 +/// @} 32.28 + 32.29 +/** get the uniform state identified by \param sidx by copying 32.30 + * a number of elements into \param val. If \param count is 0 32.31 + * then it's automatically set based on the type of this state item. 32.32 + * @{ */ 32.33 +void get_unistate(int sidx, int *val, int count = 0); 32.34 +void get_unistate(int sidx, float *val, int count = 0); 32.35 +/// @} 32.36 + 32.37 +/// convenience versions of set_unistate @{ 32.38 +void set_unistate(int sidx, int val); 32.39 +void set_unistate(int sidx, float val); 32.40 +void set_unistate(int sidx, const Vector2 &vec); 32.41 +void set_unistate(int sidx, const Vector3 &vec); 32.42 +void set_unistate(int sidx, const Vector4 &vec); 32.43 +void set_unistate(int sidx, const Matrix3x3 &mat); 32.44 +void set_unistate(int sidx, const Matrix4x4 &mat); 32.45 +/// @} 32.46 + 32.47 +/** convenience functions for setting the uniform state by name. 32.48 + * if the name cannot be found in the current set of uniform state 32.49 + * items, a new one is created with a type derived from the variant 32.50 + * of the function that was called (which might not be what you want). 32.51 + * The index of the state item is returned. 32.52 + * @{ */ 32.53 +int set_unistate(const char *name, int *val, int count = 0); 32.54 +int set_unistate(const char *name, float *val, int count = 0); 32.55 +int set_unistate(const char *name, int val); 32.56 +int set_unistate(const char *name, float val); 32.57 +int set_unistate(const char *name, const Vector2 &vec); 32.58 +int set_unistate(const char *name, const Vector3 &vec); 32.59 +int set_unistate(const char *name, const Vector4 &vec); 32.60 +int set_unistate(const char *name, const Matrix3x3 &mat); 32.61 +int set_unistate(const char *name, const Matrix4x4 &mat); 32.62 +/// @} 32.63 + 32.64 +/// convenience versions of get_unistate @{ 32.65 +int get_unistate_int(int sidx); 32.66 +float get_unistate_float(int sidx); 32.67 +Vector2 get_unistate_vec2(int sidx); 32.68 +Vector3 get_unistate_vec3(int sidx); 32.69 +Vector4 get_unistate_vec4(int sidx); 32.70 +Matrix3x3 get_unistate_mat3(int sidx); 32.71 +Matrix4x4 get_unistate_mat4(int sidx); 32.72 +/// @} 32.73 + 32.74 +/// convenience versions of get_unistate for getting the uniform state by name @{ 32.75 +int get_unistate_int(const char *name); 32.76 +float get_unistate_float(const char *name); 32.77 +Vector2 get_unistate_vec2(const char *name); 32.78 +Vector3 get_unistate_vec3(const char *name); 32.79 +Vector4 get_unistate_vec4(const char *name); 32.80 +Matrix3x3 get_unistate_mat3(const char *name); 32.81 +Matrix4x4 get_unistate_mat4(const char *name); 32.82 +/// @} 32.83 + 32.84 +/** Prepare for rendering by setting up all the state uniforms in the shader sdr. 32.85 + * If sdr is null, then use the "current" shader as per ShaderProg::current 32.86 + */ 32.87 +void setup_unistate(const ShaderProg *sdr = 0); 32.88 + 32.89 +bool setup_unistate(int sidx, const ShaderProg *sdr, int loc); 32.90 +bool setup_unistate(const char *name, const ShaderProg *sdr); 32.91 + 32.92 +// special functions for setting the rendering pipeline matrices 32.93 +void set_world_matrix(const Matrix4x4 &mat); 32.94 +void set_view_matrix(const Matrix4x4 &mat); 32.95 +void set_projection_matrix(const Matrix4x4 &mat); 32.96 +void set_texture_matrix(const Matrix4x4 &mat); 32.97 + 32.98 +Matrix4x4 get_world_matrix(); 32.99 +Matrix4x4 get_view_matrix(); 32.100 +Matrix4x4 get_projection_matrix(); 32.101 +Matrix4x4 get_texture_matrix(); 32.102 + 32.103 +void setup_gl_matrices(); // this shouldn't be needed in the final code 32.104 + 32.105 +// TODO should do a matrix stack at some point ... 32.106 + 32.107 +#endif // UNISTATE_H_
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 33.2 +++ b/src/xform_node.cc Sun Aug 24 09:41:24 2014 +0300 33.3 @@ -0,0 +1,461 @@ 33.4 +#include <assert.h> 33.5 +#include <algorithm> 33.6 +#include "xform_node.h" 33.7 +#include "anim/anim.h" 33.8 +#include "anim/track.h" 33.9 + 33.10 +static inline anm_interpolator track_interpolator(Interp in); 33.11 +static inline anm_extrapolator track_extrapolator(Extrap ex); 33.12 + 33.13 +XFormNode::XFormNode() 33.14 +{ 33.15 + anm = new anm_node; 33.16 + anm_init_node(anm); 33.17 + parent = 0; 33.18 + 33.19 + // TODO read them from anm to get the correct initial values 33.20 + interp = INTERP_LINEAR; 33.21 + extrap = EXTRAP_EXTEND; 33.22 +} 33.23 + 33.24 +XFormNode::~XFormNode() 33.25 +{ 33.26 + anm_destroy_node(anm); 33.27 + delete anm; 33.28 +} 33.29 + 33.30 +void XFormNode::set_name(const char *name) 33.31 +{ 33.32 + anm_set_node_name(anm, name); 33.33 +} 33.34 + 33.35 +const char *XFormNode::get_name() const 33.36 +{ 33.37 + return anm_get_node_name(anm); 33.38 +} 33.39 + 33.40 +void XFormNode::set_interpolator(Interp in) 33.41 +{ 33.42 + anm_set_interpolator(anm, track_interpolator(in)); 33.43 + interp = in; 33.44 +} 33.45 + 33.46 +Interp XFormNode::get_interpolator() const 33.47 +{ 33.48 + return interp; 33.49 +} 33.50 + 33.51 +void XFormNode::set_extrapolator(Extrap ex) 33.52 +{ 33.53 + anm_set_extrapolator(anm, track_extrapolator(ex)); 33.54 + extrap = ex; 33.55 +} 33.56 + 33.57 +Extrap XFormNode::get_extrapolator() const 33.58 +{ 33.59 + return extrap; 33.60 +} 33.61 + 33.62 +XFormNode *XFormNode::get_parent() 33.63 +{ 33.64 + return parent; 33.65 +} 33.66 + 33.67 +const XFormNode *XFormNode::get_parent() const 33.68 +{ 33.69 + return parent; 33.70 +} 33.71 + 33.72 +void XFormNode::add_child(XFormNode *child) 33.73 +{ 33.74 + children.push_back(child); 33.75 + anm_link_node(anm, child->anm); 33.76 + child->parent = this; 33.77 +} 33.78 + 33.79 +void XFormNode::remove_child(XFormNode *child) 33.80 +{ 33.81 + std::vector<XFormNode*>::iterator it; 33.82 + it = std::find(children.begin(), children.end(), child); 33.83 + if(it != children.end()) { 33.84 + children.erase(it); 33.85 + anm_unlink_node(anm, child->anm); 33.86 + 33.87 + if(child->parent == this) { 33.88 + child->parent = 0; 33.89 + } 33.90 + } 33.91 +} 33.92 + 33.93 +int XFormNode::get_children_count() const 33.94 +{ 33.95 + return (int)children.size(); 33.96 +} 33.97 + 33.98 +XFormNode *XFormNode::get_child(int idx) 33.99 +{ 33.100 + if(idx >= 0 && idx < get_children_count()) { 33.101 + return children[idx]; 33.102 + } 33.103 + return 0; 33.104 +} 33.105 + 33.106 +const XFormNode *XFormNode::get_child(int idx) const 33.107 +{ 33.108 + if(idx >= 0 && idx < get_children_count()) { 33.109 + return children[idx]; 33.110 + } 33.111 + return 0; 33.112 +} 33.113 + 33.114 + 33.115 +void XFormNode::use_animation(int idx) 33.116 +{ 33.117 + if(idx >= 0) { 33.118 + anm_use_animation(anm, idx); 33.119 + } 33.120 +} 33.121 + 33.122 +void XFormNode::use_animation(const char *name) 33.123 +{ 33.124 + anm_use_animation(anm, anm_find_animation(anm, name)); 33.125 +} 33.126 + 33.127 +void XFormNode::use_animation(int aidx, int bidx, float t) 33.128 +{ 33.129 + anm_use_animations(anm, aidx, bidx, t); 33.130 +} 33.131 + 33.132 +void XFormNode::use_animation(const char *aname, const char *bname, float t) 33.133 +{ 33.134 + int aidx = anm_find_animation(anm, aname); 33.135 + int bidx = anm_find_animation(anm, bname); 33.136 + 33.137 + if(aidx == -1) { 33.138 + use_animation(bidx); 33.139 + } 33.140 + if(bidx == -1) { 33.141 + use_animation(aidx); 33.142 + } 33.143 + anm_use_animations(anm, aidx, bidx, t); 33.144 +} 33.145 + 33.146 +int XFormNode::get_active_animation_index(int which) const 33.147 +{ 33.148 + return anm_get_active_animation_index(anm, which); 33.149 +} 33.150 + 33.151 +float XFormNode::get_active_animation_mix() const 33.152 +{ 33.153 + return anm_get_active_animation_mix(anm); 33.154 +} 33.155 + 33.156 +int XFormNode::get_animation_count() const 33.157 +{ 33.158 + return anm_get_animation_count(anm); 33.159 +} 33.160 + 33.161 +void XFormNode::add_animation(const char *name) 33.162 +{ 33.163 + int idx = get_animation_count(); 33.164 + 33.165 + anm_add_animation(anm); 33.166 + use_animation(idx); 33.167 + 33.168 + if(name) { 33.169 + set_animation_name(name); 33.170 + } 33.171 +} 33.172 + 33.173 +void XFormNode::set_animation_name(const char *name) 33.174 +{ 33.175 + anm_set_active_animation_name(anm, name); 33.176 +} 33.177 + 33.178 +const char *XFormNode::get_animation_name() const 33.179 +{ 33.180 + return anm_get_active_animation_name(anm); 33.181 +} 33.182 + 33.183 + 33.184 + 33.185 +void XFormNode::set_position(const Vector3 &pos, long tmsec) 33.186 +{ 33.187 + anm_set_position(anm, v3_cons(pos.x, pos.y, pos.z), ANM_MSEC2TM(tmsec)); 33.188 +} 33.189 + 33.190 +Vector3 XFormNode::get_node_position(long tmsec) const 33.191 +{ 33.192 + vec3_t p = anm_get_node_position(anm, ANM_MSEC2TM(tmsec)); 33.193 + return Vector3(p.x, p.y, p.z); 33.194 +} 33.195 + 33.196 +void XFormNode::set_rotation(const Quaternion &quat, long tmsec) 33.197 +{ 33.198 + anm_set_rotation(anm, quat_cons(quat.s, quat.v.x, quat.v.y, quat.v.z), ANM_MSEC2TM(tmsec)); 33.199 +} 33.200 + 33.201 +Quaternion XFormNode::get_node_rotation(long tmsec) const 33.202 +{ 33.203 + quat_t q = anm_get_node_rotation(anm, ANM_MSEC2TM(tmsec)); 33.204 + return Quaternion(q.w, q.x, q.y, q.z); 33.205 +} 33.206 + 33.207 +void XFormNode::set_scaling(const Vector3 &pos, long tmsec) 33.208 +{ 33.209 + anm_set_scaling(anm, v3_cons(pos.x, pos.y, pos.z), ANM_MSEC2TM(tmsec)); 33.210 +} 33.211 + 33.212 +Vector3 XFormNode::get_node_scaling(long tmsec) const 33.213 +{ 33.214 + vec3_t s = anm_get_node_scaling(anm, ANM_MSEC2TM(tmsec)); 33.215 + return Vector3(s.x, s.y, s.z); 33.216 +} 33.217 + 33.218 +// these take hierarchy into account 33.219 +Vector3 XFormNode::get_position(long tmsec) const 33.220 +{ 33.221 + vec3_t v = anm_get_position(anm, ANM_MSEC2TM(tmsec)); 33.222 + return Vector3(v.x, v.y, v.z); 33.223 +} 33.224 + 33.225 +Quaternion XFormNode::get_rotation(long tmsec) const 33.226 +{ 33.227 + quat_t q = anm_get_rotation(anm, tmsec); 33.228 + return Quaternion(q.w, q.x, q.y, q.z); 33.229 +} 33.230 + 33.231 +Vector3 XFormNode::get_scaling(long tmsec) const 33.232 +{ 33.233 + vec3_t v = anm_get_scaling(anm, ANM_MSEC2TM(tmsec)); 33.234 + return Vector3(v.x, v.y, v.z); 33.235 +} 33.236 + 33.237 +void XFormNode::set_pivot(const Vector3 &pivot) 33.238 +{ 33.239 + anm_set_pivot(anm, v3_cons(pivot.x, pivot.y, pivot.z)); 33.240 +} 33.241 + 33.242 +Vector3 XFormNode::get_pivot() const 33.243 +{ 33.244 + vec3_t p = anm_get_pivot(anm); 33.245 + return Vector3(p.x, p.y, p.z); 33.246 +} 33.247 + 33.248 +void XFormNode::set_local_matrix(const Matrix4x4 &mat) 33.249 +{ 33.250 + local_matrix = mat; 33.251 +} 33.252 + 33.253 +const Matrix4x4 &XFormNode::get_local_matrix() const 33.254 +{ 33.255 + return local_matrix; 33.256 +} 33.257 + 33.258 +void XFormNode::set_bone_matrix(const Matrix4x4 &bmat) 33.259 +{ 33.260 + bone_matrix = bmat; 33.261 +} 33.262 + 33.263 +const Matrix4x4 &XFormNode::get_bone_matrix() const 33.264 +{ 33.265 + return bone_matrix; 33.266 +} 33.267 + 33.268 +#define FOO 33.269 + 33.270 +void XFormNode::get_node_xform(long tmsec, Matrix4x4 *mat, Matrix4x4 *inv_mat) const 33.271 +{ 33.272 + anm_time_t tm = ANM_MSEC2TM(tmsec); 33.273 + 33.274 + if(mat) { 33.275 + anm_get_node_matrix(anm, (scalar_t(*)[4])mat, tm); 33.276 +#ifdef FOO 33.277 + *mat = local_matrix * *mat; 33.278 +#else 33.279 + *mat = *mat * local_matrix; 33.280 +#endif 33.281 + } 33.282 + if(inv_mat) { 33.283 + anm_get_inv_matrix(anm, (scalar_t(*)[4])inv_mat, tm); 33.284 + } 33.285 +} 33.286 + 33.287 +void XFormNode::get_xform(long tmsec, Matrix4x4 *mat, Matrix4x4 *inv_mat) const 33.288 +{ 33.289 + anm_time_t tm = ANM_MSEC2TM(tmsec); 33.290 + 33.291 + if(mat) { 33.292 + anm_get_matrix(anm, (scalar_t(*)[4])mat, tm); 33.293 +#ifdef FOO 33.294 + *mat = local_matrix * *mat; 33.295 +#else 33.296 + *mat = *mat * local_matrix; 33.297 +#endif 33.298 + } 33.299 + if(inv_mat) { 33.300 + anm_get_inv_matrix(anm, (scalar_t(*)[4])inv_mat, tm); 33.301 + } 33.302 +} 33.303 + 33.304 + 33.305 +// ---- Track ---- 33.306 + 33.307 +Track::Track() 33.308 +{ 33.309 + trk = new anm_track; 33.310 + anm_init_track(trk); 33.311 +} 33.312 + 33.313 +Track::~Track() 33.314 +{ 33.315 + anm_destroy_track(trk); 33.316 + delete trk; 33.317 +} 33.318 + 33.319 +Track::Track(const Track &rhs) 33.320 +{ 33.321 + trk = new anm_track; 33.322 + anm_init_track(trk); 33.323 + anm_copy_track(trk, rhs.trk); 33.324 + interp = rhs.interp; 33.325 + extrap = rhs.extrap; 33.326 +} 33.327 + 33.328 +Track &Track::operator =(const Track &rhs) 33.329 +{ 33.330 + if(&rhs == this) { 33.331 + return *this; 33.332 + } 33.333 + 33.334 + anm_copy_track(trk, rhs.trk); 33.335 + interp = rhs.interp; 33.336 + extrap = rhs.extrap; 33.337 + return *this; 33.338 +} 33.339 + 33.340 + 33.341 +void Track::set_interpolator(Interp in) 33.342 +{ 33.343 + anm_set_track_interpolator(trk, track_interpolator(in)); 33.344 + interp = in; 33.345 +} 33.346 + 33.347 +Interp Track::get_interpolator() const 33.348 +{ 33.349 + return interp; 33.350 +} 33.351 + 33.352 +void Track::set_extrapolator(Extrap ex) 33.353 +{ 33.354 + anm_set_track_extrapolator(trk, track_extrapolator(ex)); 33.355 + extrap = ex; 33.356 +} 33.357 + 33.358 +Extrap Track::get_extrapolator() const 33.359 +{ 33.360 + return extrap; 33.361 +} 33.362 + 33.363 +void Track::set_default(double def) 33.364 +{ 33.365 + anm_set_track_default(trk, def); 33.366 +} 33.367 + 33.368 +void Track::set_value(float val, long tmsec) 33.369 +{ 33.370 + anm_set_value(trk, ANM_MSEC2TM(tmsec), val); 33.371 +} 33.372 + 33.373 +float Track::get_value(long tmsec) const 33.374 +{ 33.375 + return anm_get_value(trk, ANM_MSEC2TM(tmsec)); 33.376 +} 33.377 + 33.378 +float Track::operator ()(long tmsec) const 33.379 +{ 33.380 + return anm_get_value(trk, ANM_MSEC2TM(tmsec)); 33.381 +} 33.382 + 33.383 + 33.384 +// ---- Track3 ---- 33.385 + 33.386 +void Track3::set_interpolator(Interp in) 33.387 +{ 33.388 + for(int i=0; i<3; i++) { 33.389 + track[i].set_interpolator(in); 33.390 + } 33.391 +} 33.392 + 33.393 +Interp Track3::get_interpolator() const 33.394 +{ 33.395 + return track[0].get_interpolator(); 33.396 +} 33.397 + 33.398 +void Track3::set_extrapolator(Extrap ex) 33.399 +{ 33.400 + for(int i=0; i<3; i++) { 33.401 + track[i].set_extrapolator(ex); 33.402 + } 33.403 +} 33.404 + 33.405 +Extrap Track3::get_extrapolator() const 33.406 +{ 33.407 + return track[0].get_extrapolator(); 33.408 +} 33.409 + 33.410 +void Track3::set_default(const Vector3 &def) 33.411 +{ 33.412 + for(int i=0; i<3; i++) { 33.413 + track[i].set_default(def[i]); 33.414 + } 33.415 +} 33.416 + 33.417 +void Track3::set_value(const Vector3 &val, long tmsec) 33.418 +{ 33.419 + for(int i=0; i<3; i++) { 33.420 + track[i].set_value(val[i], tmsec); 33.421 + } 33.422 +} 33.423 + 33.424 +Vector3 Track3::get_value(long tmsec) const 33.425 +{ 33.426 + return Vector3(track[0](tmsec), track[1](tmsec), track[2](tmsec)); 33.427 +} 33.428 + 33.429 +Vector3 Track3::operator ()(long tmsec) const 33.430 +{ 33.431 + return Vector3(track[0](tmsec), track[1](tmsec), track[2](tmsec)); 33.432 +} 33.433 + 33.434 + 33.435 +static inline anm_interpolator track_interpolator(Interp in) 33.436 +{ 33.437 + switch(in) { 33.438 + case INTERP_STEP: 33.439 + return ANM_INTERP_STEP; 33.440 + case INTERP_LINEAR: 33.441 + return ANM_INTERP_LINEAR; 33.442 + case INTERP_CUBIC: 33.443 + return ANM_INTERP_CUBIC; 33.444 + } 33.445 + 33.446 + assert(0); 33.447 + return ANM_INTERP_STEP; 33.448 +} 33.449 + 33.450 +static inline anm_extrapolator track_extrapolator(Extrap ex) 33.451 +{ 33.452 + switch(ex) { 33.453 + case EXTRAP_EXTEND: 33.454 + return ANM_EXTRAP_EXTEND; 33.455 + case EXTRAP_CLAMP: 33.456 + return ANM_EXTRAP_CLAMP; 33.457 + case EXTRAP_REPEAT: 33.458 + return ANM_EXTRAP_REPEAT; 33.459 + } 33.460 + 33.461 + assert(0); 33.462 + return ANM_EXTRAP_EXTEND; 33.463 +} 33.464 +
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 34.2 +++ b/src/xform_node.h Sun Aug 24 09:41:24 2014 +0300 34.3 @@ -0,0 +1,154 @@ 34.4 +#ifndef GOATGFX_XFORM_NODE_H_ 34.5 +#define GOATGFX_XFORM_NODE_H_ 34.6 + 34.7 +#include <vector> 34.8 +#include "vmath/vector.h" 34.9 +#include "vmath/quat.h" 34.10 +#include "vmath/matrix.h" 34.11 + 34.12 + 34.13 +struct anm_node; 34.14 +struct anm_track; 34.15 + 34.16 +enum Interp { INTERP_STEP, INTERP_LINEAR, INTERP_CUBIC }; 34.17 +enum Extrap { EXTRAP_EXTEND, EXTRAP_CLAMP, EXTRAP_REPEAT }; 34.18 + 34.19 +// NOTE: all time arguments are milliseconds 34.20 + 34.21 +class XFormNode { 34.22 +private: 34.23 + struct anm_node *anm; 34.24 + std::vector<XFormNode*> children; 34.25 + XFormNode *parent; 34.26 + 34.27 + Interp interp; 34.28 + Extrap extrap; 34.29 + 34.30 + Matrix4x4 local_matrix; 34.31 + Matrix4x4 bone_matrix; 34.32 + 34.33 + XFormNode(const XFormNode &node) {} 34.34 + XFormNode &operator =(const XFormNode &node) { return *this; } 34.35 + 34.36 +public: 34.37 + XFormNode(); 34.38 + virtual ~XFormNode(); 34.39 + 34.40 + virtual void set_name(const char *name); 34.41 + virtual const char *get_name() const; 34.42 + 34.43 + virtual void set_interpolator(Interp in); 34.44 + virtual Interp get_interpolator() const; 34.45 + virtual void set_extrapolator(Extrap ex); 34.46 + virtual Extrap get_extrapolator() const; 34.47 + 34.48 + virtual XFormNode *get_parent(); 34.49 + virtual const XFormNode *get_parent() const; 34.50 + 34.51 + // children management 34.52 + virtual void add_child(XFormNode *child); 34.53 + virtual void remove_child(XFormNode *child); 34.54 + 34.55 + virtual int get_children_count() const; 34.56 + virtual XFormNode *get_child(int idx); 34.57 + virtual const XFormNode *get_child(int idx) const; 34.58 + 34.59 + 34.60 + virtual void use_animation(int idx); 34.61 + virtual void use_animation(const char *name); 34.62 + virtual void use_animation(int aidx, int bidx, float t); 34.63 + virtual void use_animation(const char *aname, const char *bname, float t); 34.64 + 34.65 + virtual int get_active_animation_index(int which = 0) const; 34.66 + virtual float get_active_animation_mix() const; 34.67 + 34.68 + virtual int get_animation_count() const; 34.69 + 34.70 + // add a new empty animation slot (recursive) 34.71 + virtual void add_animation(const char *name = 0); 34.72 + 34.73 + // set/get the current animation name (set is recursive) 34.74 + virtual void set_animation_name(const char *name); 34.75 + virtual const char *get_animation_name() const; 34.76 + 34.77 + 34.78 + virtual void set_position(const Vector3 &pos, long tmsec = 0); 34.79 + virtual Vector3 get_node_position(long tmsec = 0) const; 34.80 + 34.81 + virtual void set_rotation(const Quaternion &quat, long tmsec = 0); 34.82 + virtual Quaternion get_node_rotation(long tmsec = 0) const; 34.83 + 34.84 + virtual void set_scaling(const Vector3 &pos, long tmsec = 0); 34.85 + virtual Vector3 get_node_scaling(long tmsec = 0) const; 34.86 + 34.87 + // these take hierarchy into account 34.88 + virtual Vector3 get_position(long tmsec = 0) const; 34.89 + virtual Quaternion get_rotation(long tmsec = 0) const; 34.90 + virtual Vector3 get_scaling(long tmsec = 0) const; 34.91 + 34.92 + virtual void set_pivot(const Vector3 &pivot); 34.93 + virtual Vector3 get_pivot() const; 34.94 + 34.95 + // the local matrix is concatenated with the regular node/anim matrix 34.96 + virtual void set_local_matrix(const Matrix4x4 &mat); 34.97 + virtual const Matrix4x4 &get_local_matrix() const; 34.98 + 34.99 + // for bone nodes, the transformation of the bone in bind position 34.100 + virtual void set_bone_matrix(const Matrix4x4 &bmat); 34.101 + virtual const Matrix4x4 &get_bone_matrix() const; 34.102 + 34.103 + // node transformation alone 34.104 + virtual void get_node_xform(long tmsec, Matrix4x4 *mat, Matrix4x4 *inv_mat = 0) const; 34.105 + 34.106 + // node transformation taking hierarchy into account 34.107 + virtual void get_xform(long tmsec, Matrix4x4 *mat, Matrix4x4 *inv_mat = 0) const; 34.108 +}; 34.109 + 34.110 + 34.111 +class Track { 34.112 +private: 34.113 + struct anm_track *trk; 34.114 + Interp interp; 34.115 + Extrap extrap; 34.116 + 34.117 +public: 34.118 + Track(); 34.119 + ~Track(); 34.120 + 34.121 + Track(const Track &trk); 34.122 + Track &operator =(const Track &trk); 34.123 + 34.124 + void set_interpolator(Interp in); 34.125 + Interp get_interpolator() const; 34.126 + void set_extrapolator(Extrap ex); 34.127 + Extrap get_extrapolator() const; 34.128 + 34.129 + void set_default(double def); 34.130 + 34.131 + void set_value(float val, long tmsec = 0); 34.132 + float get_value(long tmsec = 0) const; 34.133 + 34.134 + // the same as get_value 34.135 + float operator ()(long tmsec = 0) const; 34.136 +}; 34.137 + 34.138 +class Track3 { 34.139 +private: 34.140 + Track track[3]; 34.141 + 34.142 +public: 34.143 + void set_interpolator(Interp in); 34.144 + Interp get_interpolator() const; 34.145 + void set_extrapolator(Extrap ex); 34.146 + Extrap get_extrapolator() const; 34.147 + 34.148 + void set_default(const Vector3 &def); 34.149 + 34.150 + void set_value(const Vector3 &val, long tmsec = 0); 34.151 + Vector3 get_value(long tmsec = 0) const; 34.152 + 34.153 + // the same as get_value 34.154 + Vector3 operator ()(long tmsec = 0) const; 34.155 +}; 34.156 + 34.157 +#endif /* GOATGFX_XFORM_NODE_H_ */
35.1 --- a/vrchess.sln Sat Aug 23 12:03:29 2014 +0300 35.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 35.3 @@ -1,20 +0,0 @@ 35.4 - 35.5 -Microsoft Visual Studio Solution File, Format Version 12.00 35.6 -# Visual Studio 2012 35.7 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vrchess", "vrchess.vcxproj", "{714906B6-FD4C-4ECC-990C-247FA46B8801}" 35.8 -EndProject 35.9 -Global 35.10 - GlobalSection(SolutionConfigurationPlatforms) = preSolution 35.11 - Debug|Win32 = Debug|Win32 35.12 - Release|Win32 = Release|Win32 35.13 - EndGlobalSection 35.14 - GlobalSection(ProjectConfigurationPlatforms) = postSolution 35.15 - {714906B6-FD4C-4ECC-990C-247FA46B8801}.Debug|Win32.ActiveCfg = Debug|Win32 35.16 - {714906B6-FD4C-4ECC-990C-247FA46B8801}.Debug|Win32.Build.0 = Debug|Win32 35.17 - {714906B6-FD4C-4ECC-990C-247FA46B8801}.Release|Win32.ActiveCfg = Release|Win32 35.18 - {714906B6-FD4C-4ECC-990C-247FA46B8801}.Release|Win32.Build.0 = Release|Win32 35.19 - EndGlobalSection 35.20 - GlobalSection(SolutionProperties) = preSolution 35.21 - HideSolutionNode = FALSE 35.22 - EndGlobalSection 35.23 -EndGlobal
36.1 --- a/vrchess.vcxproj Sat Aug 23 12:03:29 2014 +0300 36.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 36.3 @@ -1,117 +0,0 @@ 36.4 -<?xml version="1.0" encoding="utf-8"?> 36.5 -<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 36.6 - <ItemGroup Label="ProjectConfigurations"> 36.7 - <ProjectConfiguration Include="Debug|Win32"> 36.8 - <Configuration>Debug</Configuration> 36.9 - <Platform>Win32</Platform> 36.10 - </ProjectConfiguration> 36.11 - <ProjectConfiguration Include="Release|Win32"> 36.12 - <Configuration>Release</Configuration> 36.13 - <Platform>Win32</Platform> 36.14 - </ProjectConfiguration> 36.15 - </ItemGroup> 36.16 - <PropertyGroup Label="Globals"> 36.17 - <ProjectGuid>{714906B6-FD4C-4ECC-990C-247FA46B8801}</ProjectGuid> 36.18 - <Keyword>Win32Proj</Keyword> 36.19 - <RootNamespace>vrchess</RootNamespace> 36.20 - </PropertyGroup> 36.21 - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> 36.22 - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> 36.23 - <ConfigurationType>Application</ConfigurationType> 36.24 - <UseDebugLibraries>true</UseDebugLibraries> 36.25 - <PlatformToolset>v120</PlatformToolset> 36.26 - <CharacterSet>MultiByte</CharacterSet> 36.27 - </PropertyGroup> 36.28 - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> 36.29 - <ConfigurationType>Application</ConfigurationType> 36.30 - <UseDebugLibraries>false</UseDebugLibraries> 36.31 - <PlatformToolset>v120</PlatformToolset> 36.32 - <WholeProgramOptimization>false</WholeProgramOptimization> 36.33 - <CharacterSet>MultiByte</CharacterSet> 36.34 - </PropertyGroup> 36.35 - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> 36.36 - <ImportGroup Label="ExtensionSettings"> 36.37 - </ImportGroup> 36.38 - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> 36.39 - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 36.40 - </ImportGroup> 36.41 - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> 36.42 - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 36.43 - </ImportGroup> 36.44 - <PropertyGroup Label="UserMacros" /> 36.45 - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> 36.46 - <LinkIncremental>true</LinkIncremental> 36.47 - </PropertyGroup> 36.48 - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> 36.49 - <LinkIncremental>false</LinkIncremental> 36.50 - </PropertyGroup> 36.51 - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> 36.52 - <ClCompile> 36.53 - <PrecompiledHeader> 36.54 - </PrecompiledHeader> 36.55 - <WarningLevel>Level3</WarningLevel> 36.56 - <Optimization>Disabled</Optimization> 36.57 - <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);USE_LIBOVR</PreprocessorDefinitions> 36.58 - <DisableSpecificWarnings>4996;4244;4305</DisableSpecificWarnings> 36.59 - <AdditionalIncludeDirectories>$(SolutionDir)\src</AdditionalIncludeDirectories> 36.60 - </ClCompile> 36.61 - <Link> 36.62 - <SubSystem>Console</SubSystem> 36.63 - <GenerateDebugInformation>true</GenerateDebugInformation> 36.64 - <AdditionalDependencies>opengl32.lib;freeglutd.lib;glew32.lib;libvmath.lib;libimago2.lib;jpeglib.lib;libpng.lib;zlib.lib;libovrd.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies> 36.65 - </Link> 36.66 - </ItemDefinitionGroup> 36.67 - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> 36.68 - <ClCompile> 36.69 - <WarningLevel>Level3</WarningLevel> 36.70 - <PrecompiledHeader> 36.71 - </PrecompiledHeader> 36.72 - <Optimization>MaxSpeed</Optimization> 36.73 - <FunctionLevelLinking>true</FunctionLevelLinking> 36.74 - <IntrinsicFunctions>true</IntrinsicFunctions> 36.75 - <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);USE_LIBOVR</PreprocessorDefinitions> 36.76 - <DisableSpecificWarnings>4996;4244;4305</DisableSpecificWarnings> 36.77 - <AdditionalIncludeDirectories>$(SolutionDir)\src</AdditionalIncludeDirectories> 36.78 - </ClCompile> 36.79 - <Link> 36.80 - <SubSystem>Console</SubSystem> 36.81 - <GenerateDebugInformation>true</GenerateDebugInformation> 36.82 - <EnableCOMDATFolding>true</EnableCOMDATFolding> 36.83 - <OptimizeReferences>true</OptimizeReferences> 36.84 - <AdditionalDependencies>opengl32.lib;freeglut.lib;glew32.lib;libvmath.lib;libimago2.lib;jpeglib.lib;libpng.lib;zlib.lib;libovr.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies> 36.85 - </Link> 36.86 - </ItemDefinitionGroup> 36.87 - <ItemGroup> 36.88 - <ClCompile Include="src\camera.cc" /> 36.89 - <ClCompile Include="src\game.cc" /> 36.90 - <ClCompile Include="src\image.cc" /> 36.91 - <ClCompile Include="src\main.cc" /> 36.92 - <ClCompile Include="src\opengl.cc" /> 36.93 - <ClCompile Include="src\sdr.c" /> 36.94 - <ClCompile Include="src\texture.cc" /> 36.95 - <ClCompile Include="src\vr\mathutil.c" /> 36.96 - <ClCompile Include="src\vr\opt.c" /> 36.97 - <ClCompile Include="src\vr\rbtree.c" /> 36.98 - <ClCompile Include="src\vr\vr.c" /> 36.99 - <ClCompile Include="src\vr\vr_libovr.c" /> 36.100 - <ClCompile Include="src\vr\vr_modules.c" /> 36.101 - <ClCompile Include="src\vr\vr_null.c" /> 36.102 - <ClCompile Include="src\vr\vr_openhmd.c" /> 36.103 - </ItemGroup> 36.104 - <ItemGroup> 36.105 - <ClInclude Include="src\camera.h" /> 36.106 - <ClInclude Include="src\game.h" /> 36.107 - <ClInclude Include="src\image.h" /> 36.108 - <ClInclude Include="src\opengl.h" /> 36.109 - <ClInclude Include="src\sdr.h" /> 36.110 - <ClInclude Include="src\texture.h" /> 36.111 - <ClInclude Include="src\vr\mathutil.h" /> 36.112 - <ClInclude Include="src\vr\opt.h" /> 36.113 - <ClInclude Include="src\vr\rbtree.h" /> 36.114 - <ClInclude Include="src\vr\vr.h" /> 36.115 - <ClInclude Include="src\vr\vr_impl.h" /> 36.116 - </ItemGroup> 36.117 - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> 36.118 - <ImportGroup Label="ExtensionTargets"> 36.119 - </ImportGroup> 36.120 -</Project> 36.121 \ No newline at end of file
37.1 --- a/vrchess.vcxproj.filters Sat Aug 23 12:03:29 2014 +0300 37.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 37.3 @@ -1,94 +0,0 @@ 37.4 -<?xml version="1.0" encoding="utf-8"?> 37.5 -<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 37.6 - <ItemGroup> 37.7 - <Filter Include="src"> 37.8 - <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> 37.9 - <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;h;inl</Extensions> 37.10 - </Filter> 37.11 - <Filter Include="src\vr"> 37.12 - <UniqueIdentifier>{e881ab02-1a45-43f6-a15d-ee7f77256a1e}</UniqueIdentifier> 37.13 - </Filter> 37.14 - </ItemGroup> 37.15 - <ItemGroup> 37.16 - <ClCompile Include="src\main.cc"> 37.17 - <Filter>src</Filter> 37.18 - </ClCompile> 37.19 - <ClCompile Include="src\camera.cc"> 37.20 - <Filter>src</Filter> 37.21 - </ClCompile> 37.22 - <ClCompile Include="src\opengl.cc"> 37.23 - <Filter>src</Filter> 37.24 - </ClCompile> 37.25 - <ClCompile Include="src\sdr.c"> 37.26 - <Filter>src</Filter> 37.27 - </ClCompile> 37.28 - <ClCompile Include="src\game.cc"> 37.29 - <Filter>src</Filter> 37.30 - </ClCompile> 37.31 - <ClCompile Include="src\image.cc"> 37.32 - <Filter>src</Filter> 37.33 - </ClCompile> 37.34 - <ClCompile Include="src\texture.cc"> 37.35 - <Filter>src</Filter> 37.36 - </ClCompile> 37.37 - <ClCompile Include="src\vr\vr.c"> 37.38 - <Filter>src\vr</Filter> 37.39 - </ClCompile> 37.40 - <ClCompile Include="src\vr\vr_libovr.c"> 37.41 - <Filter>src\vr</Filter> 37.42 - </ClCompile> 37.43 - <ClCompile Include="src\vr\vr_modules.c"> 37.44 - <Filter>src\vr</Filter> 37.45 - </ClCompile> 37.46 - <ClCompile Include="src\vr\vr_null.c"> 37.47 - <Filter>src\vr</Filter> 37.48 - </ClCompile> 37.49 - <ClCompile Include="src\vr\rbtree.c"> 37.50 - <Filter>src\vr</Filter> 37.51 - </ClCompile> 37.52 - <ClCompile Include="src\vr\opt.c"> 37.53 - <Filter>src\vr</Filter> 37.54 - </ClCompile> 37.55 - <ClCompile Include="src\vr\vr_openhmd.c"> 37.56 - <Filter>src\vr</Filter> 37.57 - </ClCompile> 37.58 - <ClCompile Include="src\vr\mathutil.c"> 37.59 - <Filter>src\vr</Filter> 37.60 - </ClCompile> 37.61 - </ItemGroup> 37.62 - <ItemGroup> 37.63 - <ClInclude Include="src\camera.h"> 37.64 - <Filter>src</Filter> 37.65 - </ClInclude> 37.66 - <ClInclude Include="src\game.h"> 37.67 - <Filter>src</Filter> 37.68 - </ClInclude> 37.69 - <ClInclude Include="src\image.h"> 37.70 - <Filter>src</Filter> 37.71 - </ClInclude> 37.72 - <ClInclude Include="src\opengl.h"> 37.73 - <Filter>src</Filter> 37.74 - </ClInclude> 37.75 - <ClInclude Include="src\sdr.h"> 37.76 - <Filter>src</Filter> 37.77 - </ClInclude> 37.78 - <ClInclude Include="src\texture.h"> 37.79 - <Filter>src</Filter> 37.80 - </ClInclude> 37.81 - <ClInclude Include="src\vr\vr.h"> 37.82 - <Filter>src\vr</Filter> 37.83 - </ClInclude> 37.84 - <ClInclude Include="src\vr\vr_impl.h"> 37.85 - <Filter>src\vr</Filter> 37.86 - </ClInclude> 37.87 - <ClInclude Include="src\vr\rbtree.h"> 37.88 - <Filter>src\vr</Filter> 37.89 - </ClInclude> 37.90 - <ClInclude Include="src\vr\opt.h"> 37.91 - <Filter>src\vr</Filter> 37.92 - </ClInclude> 37.93 - <ClInclude Include="src\vr\mathutil.h"> 37.94 - <Filter>src\vr</Filter> 37.95 - </ClInclude> 37.96 - </ItemGroup> 37.97 -</Project> 37.98 \ No newline at end of file