goat3dgfx
changeset 0:1873dfd13f2d
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 14 Nov 2013 05:27:09 +0200 |
parents | |
children | 51685f8fe859 eb75bff21824 |
files | .hgignore Makefile src/3dschunks.h src/assload.cc src/assload.h src/curve.cc src/curve.h src/curveload.cc src/curveload.h src/datapath.cc src/datapath.h src/dataset.h src/dataset.inl src/geom.cc src/geom.h src/gfxutil.cc src/gfxutil.h src/image.cc src/image.h src/logger.cc src/logger.h src/material.cc src/material.h src/mesh.cc src/mesh.h src/meshgen.cc src/meshgen.h src/object.cc src/object.h src/opengl.cc src/opengl.h src/psyspp.cc src/psyspp.h src/rtarg.cc src/rtarg.h src/scene.cc src/scene.h src/sdrman.cc src/sdrman.h src/shader.cc src/shader.h src/texgen.cc src/texgen.h src/texman.cc src/texman.h src/texture.cc src/texture.h src/timer.cc src/timer.h src/unistate.cc src/unistate.h src/xform_node.cc src/xform_node.h |
diffstat | 53 files changed, 8037 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/.hgignore Thu Nov 14 05:27:09 2013 +0200 1.3 @@ -0,0 +1,7 @@ 1.4 +\.o$ 1.5 +\.d$ 1.6 +\.swp$ 1.7 +\.a$ 1.8 +\.so\. 1.9 +\.so$ 1.10 +\.dylib$
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/Makefile Thu Nov 14 05:27:09 2013 +0200 2.3 @@ -0,0 +1,80 @@ 2.4 +PREFIX = /usr/local 2.5 + 2.6 +csrc = $(wildcard src/*.c) 2.7 +ccsrc = $(wildcard src/*.cc) 2.8 +obj = $(csrc:.c=.o) $(ccsrc:.cc=.o) 2.9 +dep = $(obj:.o=.d) 2.10 +name = goat3dgfx 2.11 +lib_a = lib$(name).a 2.12 + 2.13 +so_major = 0 2.14 +so_minor = 1 2.15 + 2.16 +ifeq ($(shell uname -r), Darwin) 2.17 + libgl = -framework OpenGL -framework GLUT -lGLEW 2.18 + 2.19 + lib_so = lib$(name).dylib 2.20 + shared = -dynamiclib 2.21 +else 2.22 + libgl = -lGL -lGLU -lglut -lGLEW 2.23 + 2.24 + lib_so = lib$(name).so.$(so_major).$(so_minor) 2.25 + soname = lib$(name).so.$(so_major) 2.26 + devlink = lib$(name).so 2.27 + shared = -shared -Wl,-soname=$(soname) 2.28 + pic = -fPIC 2.29 +endif 2.30 + 2.31 + 2.32 +CFLAGS = -pedantic $(warn) $(dbg) $(pic) $(opt) $(inc) $(libs_cflags) 2.33 +CXXFLAGS = $(CFLAGS) 2.34 +LDFLAGS = $(libgl) $(libs_ldflags) 2.35 + 2.36 +.PHONY: all 2.37 +all: $(lib_so) $(lib_a) 2.38 + 2.39 +$(lib_a): $(obj) 2.40 + $(AR) rcs $@ $(obj) 2.41 + 2.42 +$(lib_so): $(obj) 2.43 + $(CXX) $(shared) -o $@ $(obj) $(LDFLAGS) 2.44 + 2.45 +-include $(dep) 2.46 + 2.47 +%.d: %.c 2.48 + @$(CPP) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@ 2.49 + 2.50 +%.d: %.cc 2.51 + @$(CPP) $(CXXFLAGS) $< -MM -MT $(@:.d=.o) >$@ 2.52 + 2.53 +.PHONY: clean 2.54 +clean: 2.55 + rm -f $(obj) $(lib_a) $(lib_so) 2.56 + 2.57 +.PHONY: cleandep 2.58 +cleandep: 2.59 + rm -f $(dep) 2.60 + 2.61 +.PHONY: install 2.62 +install: $(lib_so) $(lib_a) 2.63 + mkdir -p $(DESTDIR)$(PREFIX)/lib $(DESTDIR)$(PREFIX)/include/goat3dgfx 2.64 + cp src/*.h src/*.inl $(DESTDIR)$(PREFIX)/include/goat3dgfx/ 2.65 + cp $(lib_a) $(DESTDIR)$(PREFIX)/lib/$(lib_a) 2.66 + cp $(lib_so) $(DESTDIR)$(PREFIX)/lib/$(lib_so) 2.67 + [ -n "$(devlink)" ] && \ 2.68 + cd $(DESTDIR)$(PREFIX)/lib && \ 2.69 + rm -f $(soname) $(devlink) && \ 2.70 + ln -s $(lib_so) $(soname) && \ 2.71 + ln -s $(soname) $(devlink) || \ 2.72 + true 2.73 + 2.74 +.PHONY: uninstall 2.75 +uninstall: 2.76 + rm -f $(DESTDIR)$(PREFIX)/include/goat3dgfx/* 2.77 + rmdir $(DESTDIR)$(PREFIX)/include/goat3dgfx 2.78 + rm -f $(DESTDIR)$(PREFIX)/lib/$(lib_so) 2.79 + rm -f $(DESTDIR)$(PREFIX)/lib/$(lib_a) 2.80 + [ -n "$(devlink)" ] && \ 2.81 + rm -f $(DESTDIR)$(PREFIX)/lib/$(soname) && \ 2.82 + rm -f $(DESTDIR)$(PREFIX)/lib/$(devlink) || \ 2.83 + true
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/src/3dschunks.h Thu Nov 14 05:27:09 2013 +0200 3.3 @@ -0,0 +1,160 @@ 3.4 +#ifndef _3DSCHUNKS_H_ 3.5 +#define _3DSCHUNKS_H_ 3.6 + 3.7 +enum ChunkID { 3.8 + Chunk_Color_Float3 = 0x0010, // o Floating point color 3.9 + Chunk_Color_Byte3 = 0x0011, // o 24bit color 3.10 + Chunk_Color_GammaByte3 = 0x0012, // o 24bit gamma corrected 3.11 + Chunk_Color_GammaFloat3 = 0x0013, // o Floating point gamma corrected 3.12 + Chunk_PercentInt = 0x0030, // o Percent Chunk int 0 - 100 3.13 + Chunk_PercentFloat = 0x0031, // o Percent Chunk float 0 - 1 3.14 + 3.15 + Chunk_3DSMain = 0x4D4D, // + Root Chunk 3.16 + Chunk_Main_3DSVersion = 0x0002, // - 3DS Version 3.17 + Chunk_Main_3DEditor = 0x3D3D, // + 3D Editor Chunk 3.18 + Chunk_Edit_Unit = 0x0100, // - Unit 3.19 + Chunk_Edit_BGBitmap = 0x1100, // - Background Bitmap 3.20 + Chunk_Edit_UseBGBitmap = 0x1101, // - Use Background Bitmap 3.21 + Chunk_Edit_BGColor = 0x1200, // - Background Color 3.22 + Chunk_Edit_UseBGColor = 0x1201, // - Use Background Color 3.23 + Chunk_Edit_GradColor = 0x1300, // - Background Gradient 3.24 + Chunk_Edit_UseGradColor = 0x1301, // - Use Gradient Color 3.25 + Chunk_Edit_ShadowMapBias = 0x1400, // - Shadow map bias 3.26 + Chunk_Edit_ShadowMapSize = 0x1420, // - Shadow map size 3.27 + Chunk_Edit_ShadowMapSampleRange = 0x1450, // - Shadow map sample range 3.28 + Chunk_Edit_RaytraceBias = 0x1460, // - Raytrace bias 3.29 + Chunk_Edit_UseRaytrace = 0x1470, // - Use Raytrace 3.30 + Chunk_Edit_AmbientColor = 0x2100, // - Ambient Color 3.31 + Chunk_Edit_Fog = 0x2200, // + Fog 3.32 + Chunk_Fog_FogColor = 0x2210, // - Fog Color 3.33 + Chunk_Edit_UseFog = 0x2201, // - Use Fog 3.34 + Chunk_Edit_DistanceQue = 0x2300, // + Distance que 3.35 + Chunk_Dist_DimBackground = 0x2310, // - Dim Background 3.36 + Chunk_Edit_UseDistanceQue = 0x2301, // - Use distance que 3.37 + Chunk_Edit_LayeredFogOptions = 0x2302, // - Layered fog options 3.38 + Chunk_Edit_UseLayeredFog = 0x2303, // - Use Layered Fog 3.39 + Chunk_Edit_MeshVersion = 0x3D3E, // - Mesh Version 3.40 + 3.41 + Chunk_Edit_Object = 0x4000, // + Object 3.42 + Chunk_Obj_Hidden = 0x4010, // - Hidden 3.43 + Chunk_Obj_DontCastShadows = 0x4012, // - Object doesn't cast shadows 3.44 + Chunk_Obj_MatteObject = 0x4013, // - Matte 3.45 + Chunk_Obj_ExternalProcessOn = 0x4015, // - External Process on (?) 3.46 + Chunk_Obj_DontReceiveShadows = 0x4017, // - doesn't reseive shadows 3.47 + Chunk_Obj_TriMesh = 0x4100, // + TriMesh 3.48 + Chunk_TriMesh_VertexList = 0x4110, // - Vertex List 3.49 + Chunk_TriMesh_FaceDesc = 0x4120, // + Faces description 3.50 + Chunk_Face_Material = 0x4130, // - Face Materials* 3.51 + Chunk_TriMesh_TexCoords = 0x4140, // - Texture Coordinates 3.52 + Chunk_TriMesh_SmoothingGroup = 0x4150, // - Smoothing group 3.53 + Chunk_TriMesh_WorldTransform = 0x4160, // - Position and Orientation 3.54 + Chunk_TriMesh_Color = 0x4165, // - Object color 3.55 + Chunk_TriMesh_ExternalProcessName = 0x4181, // - External Process name (?) 3.56 + Chunk_TriMesh_ExternalProcessParams = 0x4182, // - External Process parameters (?) 3.57 + 3.58 + Chunk_Obj_Light = 0x4600, // + Light 3.59 + Chunk_Light_SpotLight = 0x4610, // + SpotLight 3.60 + Chunk_Spot_Raytrace = 0x4627, // - Raytrace 3.61 + Chunk_Spot_CastShadows = 0x4630, // - Light casts shadows 3.62 + Chunk_Spot_ShadowMap = 0x4641, // - Shadow Map 3.63 + Chunk_Spot_ShowCone = 0x4650, // - Show Cone 3.64 + Chunk_Spot_Rectangular = 0x4651, // - Rectangular shaped spotlight 3.65 + Chunk_Spot_OverShoot = 0x4652, // - Overshoot 3.66 + Chunk_Spot_ProjMap = 0x4653, // - Projector Map 3.67 + Chunk_Spot_Roll = 0x4656, // - Roll around dir 3.68 + Chunk_Spot_RaytraceBias = 0x4658, // - Raytrace Bias 3.69 + Chunk_Light_Off = 0x4620, // - Light is disabled 3.70 + Chunk_Light_Attenuation = 0x4625, // - Attenuation enabled 3.71 + Chunk_Light_AttenuationStart = 0x4659, // - Attenuation Start Range 3.72 + Chunk_Light_AttenuationEnd = 0x465A, // - Attenuation End Range 3.73 + Chunk_Light_Intensity = 0x465B, // - Light Intensity 3.74 + 3.75 + Chunk_Obj_Camera = 0x4700, // - Camera 3.76 + Chunk_Edit_ViewSettings = 0x7001, // - View Settings 3.77 + Chunk_Edit_ViewDesc2 = 0x7011, // - View Description 2 3.78 + Chunk_Edit_ViewDesc1 = 0x7012, // - View Description 1 3.79 + Chunk_Edit_MeshWindows = 0x7020, // - Mesh Windows (?) 3.80 + 3.81 + Chunk_Edit_Material = 0xAFFF, // + Material Block 3.82 + Chunk_Mat_Name = 0xA000, // - Material Name 3.83 + Chunk_Mat_AmbientColor = 0xA010, // - Ambient Color 3.84 + Chunk_Mat_DiffuseColor = 0xA020, // - Diffuse Color 3.85 + Chunk_Mat_SpecularColor = 0xA030, // - Specular Color 3.86 + Chunk_Mat_Specular = 0xA040, // - Shininness (Specular Power) 3.87 + Chunk_Mat_SpecularIntensity = 0xA041, // - Shininness Strength (specular intensity) 3.88 + Chunk_Mat_Transparency = 0xA050, // - Transparency (alpha) 3.89 + Chunk_Mat_TransparencyFalloff = 0xA052, // - Transparency Falloff 3.90 + Chunk_Mat_ReflectionBlur = 0xA053, // - Reflection Blur 3.91 + Chunk_Mat_TwoSided = 0xA081, // - Two Sided 3.92 + Chunk_Mat_AddTransparency = 0xA083, // - ? 3.93 + Chunk_Mat_SelfIllumination = 0xA084, // - Self Illumination (emissive) 3.94 + Chunk_Mat_Wireframe = 0xA085, // - Render in wireframe 3.95 + Chunk_Mat_WireframeThickness = 0xA087, // - Wire thickness 3.96 + Chunk_Mat_FaceMapping = 0xA088, // - Apply maps to faces seperatly (ignore uv) 3.97 + Chunk_Mat_InTranc = 0xA08A, // ? 3.98 + Chunk_Mat_Soften = 0xA08C, // - Soft Shading 3.99 + Chunk_Mat_WireUnits = 0xA08E, // - Wire units (?) 3.100 + Chunk_Mat_RenderType = 0xA100, // - Render Type 3.101 + Chunk_Mat_BumpMapPercent = 0xA252, // - Bump map intensity 3.102 + Chunk_Mat_TextureMap = 0xA200, // + Texture Map 3.103 + Chunk_Mat_TextureMap2 = 0xA33A, // + Texture Map 2 3.104 + Chunk_Mat_OpacityMap = 0xA210, // + Opacity Map 3.105 + Chunk_Mat_BumpMap = 0xA230, // + Bump Map 3.106 + Chunk_Mat_SpecularMap = 0xA33C, // + Specular Intensity map 3.107 + Chunk_Mat_SpecularColorMap = 0xA204, // + Specular color (texture) map 3.108 + Chunk_Mat_SelfIlluminationMap = 0xA33D, // + Self Illumination Map 3.109 + Chunk_Mat_ReflectionMap = 0xA220, // + Reflection Map 3.110 + Chunk_Mat_TextureMask = 0xA33E, // - Texture Mask 3.111 + Chunk_Mat_Texture2Mask = 0xA340, // - Texture 2 Mask 3.112 + Chunk_Mat_OpacityMask = 0xA342, // - Opacity Mask 3.113 + Chunk_Mat_BumpMask = 0xA344, // - Bump Mask 3.114 + Chunk_Mat_SpecularMask = 0xA346, // - Specular Mask 3.115 + Chunk_Mat_SpecularColorMask = 0xA348, // - Specular color mask 3.116 + Chunk_Mat_SelfIlluminationMask = 0xA34A, // - Self Illumination mask 3.117 + Chunk_Mat_ReflectionMask = 0xA34C, // - Reflection mask 3.118 + 3.119 + // map subchunks // ----------------------- 3.120 + Chunk_Map_FileName = 0xA300, // - Filename 3.121 + Chunk_Map_Params = 0xA351, // - Parameters 3.122 + Chunk_Map_BlurPercent = 0xA353, // - Blur ammount 3.123 + Chunk_Map_VScale = 0xA354, // - Texture V Scale 3.124 + Chunk_Map_UScale = 0xA356, // - Texture U Scale 3.125 + Chunk_Map_UOffset = 0xA358, // - Texture U Offset 3.126 + Chunk_MAP_VOffset = 0xA35A, // - Texture V Offset 3.127 + Chunk_Map_RotationAngle = 0xA35C, // - Texture Rotation Angle 3.128 + Chunk_Map_RGBLumAlphaTint1 = 0xA360, // - RGB Luminance Alpha Tint 1 3.129 + Chunk_Map_RGBLumAlphaTint2 = 0xA362, // - RGB Luminance Alpha Tint 2 3.130 + Chunk_Map_RGBTintR = 0xA364, // - RGB Tint R 3.131 + Chunk_Map_RGBTintG = 0xA366, // - RGB Tint G 3.132 + Chunk_Map_RGBTintB = 0xA368, // - RGB Tint B 3.133 + // map subchunks end // ----------------------- 3.134 + 3.135 + Chunk_Main_Keyframer = 0xB000, // + Keyframer Chunk 3.136 + Chunk_Key_AmbientInfo = 0xB001, // - Ambient animation info 3.137 + Chunk_Key_MeshInfo = 0xB002, // - Mesh animation info 3.138 + Chunk_Key_CameraInfo = 0xB003, // - Camera animation info 3.139 + Chunk_Key_CameraTargetInfo = 0xB004, // - Camera Target animation info 3.140 + Chunk_Key_OmniLightInfo = 0xB005, // - Omni Light animation info 3.141 + Chunk_Key_SpotLightTargetInfo = 0xB006, // - Spotlight target animation info 3.142 + Chunk_Key_SpotLightInfo = 0xB007, // - Spotlight animation info 3.143 + Chunk_Key_Frames = 0xB008, // - Animation Frames 3.144 + 3.145 + // animation information subchunks // ----------------------- 3.146 + Chunk_Info_Object = 0xB010, // - Object information 3.147 + Chunk_Info_ObjectPivot = 0xB013, // - Object Pivot 3.148 + Chunk_Info_ObjectMorphAngle = 0xB015, // - Object Morph Angle 3.149 + Chunk_Info_PositionTrack = 0xB020, // - Position Track 3.150 + Chunk_Info_RotationTrack = 0xB021, // - Rotation Track 3.151 + Chunk_Info_ScaleTrack = 0xB022, // - Scaling Track 3.152 + Chunk_Info_FOVTrack = 0xB023, // - FOV Track 3.153 + Chunk_Info_RollTrack = 0xB024, // - Roll Track 3.154 + Chunk_Info_ColorTrack = 0xB025, // - Color Track 3.155 + Chunk_Info_MorphTrack = 0xB026, // - Morph Track 3.156 + Chunk_Info_HotSpotTrack = 0xB027, // - HotSpot Track 3.157 + Chunk_Info_FalloffTrack = 0xB028, // - Falloff Track 3.158 + Chunk_Info_HideTrack = 0xB029, // - Hide Track 3.159 + Chunk_Info_HierarchyPosition = 0xB030 // - Hierarchy Position 3.160 +}; 3.161 + 3.162 +#endif // _3DSCHUNKS_H_ 3.163 +
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/assload.cc Thu Nov 14 05:27:09 2013 +0200 4.3 @@ -0,0 +1,437 @@ 4.4 +#include <stdio.h> 4.5 +#include "assload.h" 4.6 +#include "logger.h" 4.7 +#include "datapath.h" 4.8 + 4.9 +#ifdef USE_ASSIMP 4.10 + 4.11 +#include <vector> 4.12 +#include <map> 4.13 +#include "assimp/cimport.h" 4.14 +#include "assimp/scene.h" 4.15 +#include "assimp/postprocess.h" 4.16 +#include "texman.h" 4.17 +#include "material.h" 4.18 + 4.19 +using namespace std; 4.20 + 4.21 +static bool load_material(Material *mat, const aiMaterial *aimat); 4.22 +static Object *load_node(const aiScene *aiscn, const aiNode *ainode); 4.23 +static Mesh *load_mesh(const aiScene *aiscn, const aiMesh *aimesh); 4.24 +static Curve *load_curve(const aiScene *aiscn, const aiMesh *aimesh); 4.25 +static bool load_bones(Mesh *mesh, const aiMesh *aimesh); 4.26 + 4.27 +static Vector3 assimp_vector(const aiVector3D &v); 4.28 +static Quaternion assimp_quat(const aiQuaternion &q); 4.29 +static Matrix4x4 assimp_matrix(const aiMatrix4x4 &aim); 4.30 +static long assimp_time(const aiAnimation *anim, double aitime); 4.31 +static void print_hierarchy(const aiNode *node); 4.32 + 4.33 +static map<string, Object*> obj_by_name; 4.34 +static map<aiMesh*, Mesh*> mesh_by_aimesh; 4.35 + 4.36 +bool load_ass(Scene *scn, const char *fname) 4.37 +{ 4.38 + static bool init_done; 4.39 + 4.40 + if(!init_done) { 4.41 + static aiLogStream log_stream = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT, 0); 4.42 + aiAttachLogStream(&log_stream); 4.43 + //aiEnableVerboseLogging(1); 4.44 + init_done = true; 4.45 + } 4.46 + 4.47 + unsigned int proc_flags = aiProcess_JoinIdenticalVertices | 4.48 + aiProcess_CalcTangentSpace | 4.49 + aiProcess_Triangulate | 4.50 + aiProcess_SortByPType | 4.51 + aiProcess_FlipUVs; 4.52 + 4.53 + const aiScene *aiscn = aiImportFile(datafile_path(fname).c_str(), proc_flags); 4.54 + if(!aiscn) { 4.55 + error_log("failed to load file: %s\n", fname); 4.56 + return false; 4.57 + } 4.58 + 4.59 + info_log("NODE HIERARCHY:\n"); 4.60 + print_hierarchy(aiscn->mRootNode); 4.61 + info_log("-------------------\n"); 4.62 + 4.63 + Vector3 root_pos, root_scaling(1.0, 1.0, 1.0); 4.64 + Quaternion root_rot; 4.65 + 4.66 + if(aiscn->mRootNode) { 4.67 + Matrix4x4 root_matrix = assimp_matrix(aiscn->mRootNode->mTransformation); 4.68 + root_pos = root_matrix.get_translation(); 4.69 + root_rot = root_matrix.get_rotation_quat(); 4.70 + root_scaling = root_matrix.get_scaling(); 4.71 + } 4.72 + 4.73 + // load all meshes 4.74 + for(unsigned int i=0; i<aiscn->mNumMeshes; i++) { 4.75 + aiMesh *aimesh = aiscn->mMeshes[i]; 4.76 + Mesh *mesh; 4.77 + Curve *curve; 4.78 + 4.79 + switch(aimesh->mPrimitiveTypes) { 4.80 + case aiPrimitiveType_TRIANGLE: 4.81 + if((mesh = load_mesh(aiscn, aimesh))) { 4.82 + mesh_by_aimesh[aimesh] = mesh; 4.83 + scn->meshes.push_back(mesh); 4.84 + } 4.85 + break; 4.86 + 4.87 + case aiPrimitiveType_LINE: 4.88 + if((curve = load_curve(aiscn, aimesh))) { 4.89 + scn->curves.push_back(curve); 4.90 + } 4.91 + break; 4.92 + 4.93 + default: 4.94 + error_log("unsupported primitive type: %u\n", aimesh->mPrimitiveTypes); 4.95 + break; 4.96 + } 4.97 + } 4.98 + 4.99 + // load all the nodes recursively 4.100 + for(unsigned int i=0; i<aiscn->mRootNode->mNumChildren; i++) { 4.101 + Object *obj = load_node(aiscn, aiscn->mRootNode->mChildren[i]); 4.102 + if(obj) { 4.103 + Object *dummy = new Object; 4.104 + dummy->set_name((string("dummyroot_") + string(obj->get_name())).c_str()); 4.105 + dummy->set_position(root_pos); 4.106 + dummy->set_rotation(root_rot); 4.107 + dummy->set_scaling(root_scaling); 4.108 + dummy->add_child(obj); 4.109 + 4.110 + obj = dummy; 4.111 + scn->objects.push_back(obj); 4.112 + } 4.113 + } 4.114 + 4.115 + // load and attach the bones to the meshes 4.116 + for(unsigned int i=0; i<aiscn->mNumMeshes; i++) { 4.117 + aiMesh *aimesh = aiscn->mMeshes[i]; 4.118 + 4.119 + Mesh *mesh = mesh_by_aimesh[aimesh]; 4.120 + load_bones(mesh, aimesh); 4.121 + } 4.122 + 4.123 + obj_by_name.clear(); 4.124 + mesh_by_aimesh.clear(); 4.125 + 4.126 + aiReleaseImport(aiscn); 4.127 + return true; 4.128 +} 4.129 + 4.130 +static bool load_material(Material *mat, const aiMaterial *aimat) 4.131 +{ 4.132 + aiColor4D aicol; 4.133 + float shin, shin_str; 4.134 + 4.135 + if(aiGetMaterialColor(aimat, AI_MATKEY_COLOR_DIFFUSE, &aicol) == 0) { 4.136 + mat->diffuse = Vector3(aicol[0], aicol[1], aicol[2]); 4.137 + } 4.138 + if(aiGetMaterialColor(aimat, AI_MATKEY_COLOR_SPECULAR, &aicol) == 0) { 4.139 + mat->specular = Vector3(aicol[0], aicol[1], aicol[2]); 4.140 + } 4.141 + 4.142 + unsigned int count = 1; 4.143 + if(aiGetMaterialFloatArray(aimat, AI_MATKEY_SHININESS_STRENGTH, &shin_str, &count) != 0) { 4.144 + shin_str = 1.0; 4.145 + } 4.146 + if(aiGetMaterialFloatArray(aimat, AI_MATKEY_SHININESS, &shin, &count) == 0) { 4.147 + // XXX can't remember how I came up with this... 4.148 + mat->shininess = shin * shin_str * 0.0001 * 128.0; 4.149 + } 4.150 + 4.151 + // load textures 4.152 + struct { int type; aiTextureType aitype; } textypes[] = { 4.153 + {TEX_DIFFUSE, aiTextureType_DIFFUSE}, 4.154 + {TEX_NORMAL, aiTextureType_NORMALS}, 4.155 + {TEX_SPECULAR, aiTextureType_SPECULAR} 4.156 + }; 4.157 + 4.158 + for(int i=0; i<sizeof textypes / sizeof *textypes; i++) { 4.159 + aiString aipath; 4.160 + 4.161 + if(aiGetMaterialTexture(aimat, textypes[i].aitype, 0, &aipath) == 0) { 4.162 + char *tmp, *fname = aipath.data; 4.163 + 4.164 + if((tmp = strrchr(fname, '/'))) { 4.165 + fname = tmp + 1; 4.166 + } 4.167 + if((tmp = strrchr(fname, '\\'))) { 4.168 + fname = tmp + 1; 4.169 + } 4.170 + 4.171 + if(*fname) { 4.172 + mat->tex[textypes[i].type] = texset.get(fname); 4.173 + } 4.174 + } 4.175 + } 4.176 + 4.177 + return true; 4.178 +} 4.179 + 4.180 +static Object *load_node(const aiScene *aiscn, const aiNode *ainode) 4.181 +{ 4.182 + Object *obj = new Object; 4.183 + obj->set_name(ainode->mName.data); 4.184 + 4.185 + if(ainode->mNumMeshes) { 4.186 + if(ainode->mNumMeshes > 1) { 4.187 + info_log("%s warning: node %s has more than one meshes (%u)\n", __FUNCTION__, 4.188 + ainode->mName.data, ainode->mNumMeshes); 4.189 + } 4.190 + 4.191 + aiMesh *aimesh = aiscn->mMeshes[ainode->mMeshes[0]]; 4.192 + obj->set_mesh(mesh_by_aimesh[aimesh]); 4.193 + 4.194 + // also grab the material of this mesh 4.195 + load_material(&obj->material, aiscn->mMaterials[aimesh->mMaterialIndex]); 4.196 + } 4.197 + 4.198 + // if there are animations, grab the first and try to use it 4.199 + if(aiscn->mNumAnimations) { 4.200 + aiAnimation *aianim = aiscn->mAnimations[0]; 4.201 + aiNodeAnim *ainodeanim = 0; 4.202 + for(unsigned int i=0; i<aianim->mNumChannels; i++) { 4.203 + if(strcmp(aianim->mChannels[i]->mNodeName.data, ainode->mName.data) == 0) { 4.204 + ainodeanim = aianim->mChannels[i]; 4.205 + break; 4.206 + } 4.207 + } 4.208 + 4.209 + if(ainodeanim) { 4.210 + // load all position (translation) keyframes 4.211 + for(unsigned int i=0; i<ainodeanim->mNumPositionKeys; i++) { 4.212 + Vector3 pos = assimp_vector(ainodeanim->mPositionKeys[i].mValue); 4.213 + long msec = assimp_time(aianim, ainodeanim->mPositionKeys[i].mTime); 4.214 + obj->set_position(pos, msec); 4.215 + } 4.216 + 4.217 + // load all rotation keyframes 4.218 + for(unsigned int i=0; i<ainodeanim->mNumRotationKeys; i++) { 4.219 + Quaternion rot = assimp_quat(ainodeanim->mRotationKeys[i].mValue); 4.220 + if(rot.length_sq() < SMALL_NUMBER) { 4.221 + continue; 4.222 + } 4.223 + rot.normalize(); 4.224 + long msec = assimp_time(aianim, ainodeanim->mRotationKeys[i].mTime); 4.225 + obj->set_rotation(rot, msec); 4.226 + } 4.227 + 4.228 + // load all scaling keyframes 4.229 + for(unsigned int i=0; i<ainodeanim->mNumScalingKeys; i++) { 4.230 + Vector3 scale = assimp_vector(ainodeanim->mScalingKeys[i].mValue); 4.231 + long msec = assimp_time(aianim, ainodeanim->mScalingKeys[i].mTime); 4.232 + obj->set_scaling(scale, msec); 4.233 + } 4.234 + 4.235 + obj->set_extrapolator(EXTRAP_REPEAT); // loop animation 4.236 + } else { 4.237 + Matrix4x4 local_matrix = assimp_matrix(ainode->mTransformation); 4.238 + obj->set_local_matrix(local_matrix); 4.239 + } 4.240 + } 4.241 + 4.242 + /* recurse to all children */ 4.243 + for(unsigned int i=0; i<ainode->mNumChildren; i++) { 4.244 + Object *child = load_node(aiscn, ainode->mChildren[i]); 4.245 + if(child) { 4.246 + obj->add_child(child); 4.247 + } 4.248 + } 4.249 + 4.250 + obj_by_name[obj->get_name()] = obj; 4.251 + return obj; 4.252 +} 4.253 + 4.254 +static Mesh *load_mesh(const aiScene *aiscn, const aiMesh *aimesh) 4.255 +{ 4.256 + Mesh *mesh = new Mesh; 4.257 + 4.258 + int num_verts = aimesh->mNumVertices; 4.259 + int num_faces = aimesh->mNumFaces; 4.260 + 4.261 + mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, (float*)aimesh->mVertices); 4.262 + 4.263 + if(aimesh->mNormals) { 4.264 + mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, (float*)aimesh->mNormals); 4.265 + } 4.266 + if(aimesh->mTangents) { 4.267 + mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, (float*)aimesh->mTangents); 4.268 + } 4.269 + if(aimesh->mTextureCoords[0]) { 4.270 + mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 3, num_verts, (float*)aimesh->mTextureCoords[0]); 4.271 + } 4.272 + 4.273 + if(aimesh->mBones) { 4.274 + float *weights = mesh->set_attrib_data(MESH_ATTR_BONEWEIGHTS, 4, num_verts, 0); 4.275 + float *boneidx = mesh->set_attrib_data(MESH_ATTR_BONEIDX, 4, num_verts, 0); 4.276 + 4.277 + memset(weights, 0, num_verts * 4 * sizeof *weights); 4.278 + memset(boneidx, 0, num_verts * 4 * sizeof *boneidx); 4.279 + 4.280 + int *vertex_bone_count = new int[num_verts]; 4.281 + memset(vertex_bone_count, 0, num_verts * sizeof *vertex_bone_count); 4.282 + 4.283 + for(unsigned int i=0; i<aimesh->mNumBones; i++) { 4.284 + aiBone *aibone = aimesh->mBones[i]; 4.285 + 4.286 + // for every vertex affected by this bone: 4.287 + for(unsigned int j=0; j<aibone->mNumWeights; j++) { 4.288 + aiVertexWeight *aiweight = aibone->mWeights + j; 4.289 + int vidx = aiweight->mVertexId; 4.290 + int vert_boneidx = vertex_bone_count[vidx]; 4.291 + if(vert_boneidx >= 4) { 4.292 + error_log("WARNING vertex with more than 4 bones found\n"); 4.293 + continue; 4.294 + } 4.295 + 4.296 + weights[vidx * 4 + vert_boneidx] = aiweight->mWeight; 4.297 + boneidx[vidx * 4 + vert_boneidx] = (float)i; 4.298 + vertex_bone_count[vidx]++; 4.299 + } 4.300 + } 4.301 + 4.302 + delete [] vertex_bone_count; 4.303 + 4.304 + // normalize weights 4.305 + for(int i=0; i<num_verts; i++) { 4.306 + 4.307 + float wsum = 0.0f; 4.308 + 4.309 + for(int j=0; j<4; j++) { 4.310 + wsum += weights[i * 4 + j]; 4.311 + } 4.312 + 4.313 + if(1.0 - wsum > 1e-4) { 4.314 + error_log("WARNING vertex with weights < 1 (%f), normalizing...\n", wsum); 4.315 + 4.316 + if(wsum < 1e-6) { 4.317 + // this is clearly broken, let's use the first bone in full 4.318 + weights[i * 4] = 1.0; 4.319 + } else { 4.320 + weights[i * 4] /= wsum; 4.321 + weights[i * 4 + 1] /= wsum; 4.322 + weights[i * 4 + 2] /= wsum; 4.323 + weights[i * 4 + 3] /= wsum; 4.324 + } 4.325 + } 4.326 + } 4.327 + } 4.328 + 4.329 + unsigned int *iptr = mesh->set_index_data(num_faces * 3); 4.330 + for(int i=0; i<num_faces; i++) { 4.331 + for(int j=0; j<3; j++) { 4.332 + *iptr++ = aimesh->mFaces[i].mIndices[j]; 4.333 + } 4.334 + } 4.335 + 4.336 + return mesh; 4.337 +} 4.338 + 4.339 +static Curve *load_curve(const aiScene *aiscn, const aiMesh *aimesh) 4.340 +{ 4.341 + Curve *curve = new Curve; 4.342 + 4.343 + for(unsigned int i=0; i<aimesh->mNumVertices; i++) { 4.344 + Vector3 pt = assimp_vector(aimesh->mVertices[i]); 4.345 + curve->add_point(pt); 4.346 + } 4.347 + info_log("loaded curve with %d points\n", aimesh->mNumVertices); 4.348 + 4.349 + return curve; 4.350 +} 4.351 + 4.352 +static bool load_bones(Mesh *mesh, const aiMesh *aimesh) 4.353 +{ 4.354 + if(!aimesh->mNumBones) { 4.355 + return false; 4.356 + } 4.357 + 4.358 + for(unsigned int i=0; i<aimesh->mNumBones; i++) { 4.359 + aiBone *aibone = aimesh->mBones[i]; 4.360 + Object *obj = obj_by_name[aibone->mName.data]; 4.361 + if(!obj) { 4.362 + error_log("bone %s not found\n", aibone->mName.data); 4.363 + continue; 4.364 + } 4.365 + 4.366 + obj->set_bone_matrix(assimp_matrix(aibone->mOffsetMatrix)); 4.367 + mesh->add_bone(obj); 4.368 + 4.369 + info_log("adding bone: %s\n", obj->get_name()); 4.370 + } 4.371 + 4.372 + return true; 4.373 +} 4.374 + 4.375 +static Vector3 assimp_vector(const aiVector3D &v) 4.376 +{ 4.377 + return Vector3(v[0], v[1], v[2]); 4.378 +} 4.379 + 4.380 +static Quaternion assimp_quat(const aiQuaternion &q) 4.381 +{ 4.382 + return Quaternion(q.w, Vector3(q.x, q.y, q.z)); 4.383 +} 4.384 + 4.385 +static Matrix4x4 assimp_matrix(const aiMatrix4x4 &aim) 4.386 +{ 4.387 + Matrix4x4 m; 4.388 + memcpy(m[0], &aim, 16 * sizeof(float)); 4.389 + return m; 4.390 +} 4.391 + 4.392 +/* convert an assimp keyframe time (ticks) into milliseconds */ 4.393 +static long assimp_time(const aiAnimation *anim, double aitime) 4.394 +{ 4.395 + double sec; 4.396 + if(anim->mTicksPerSecond < 1e-6) { 4.397 + // assume time is in frames? 4.398 + sec = aitime / 30.0; 4.399 + } else { 4.400 + sec = aitime / anim->mTicksPerSecond; 4.401 + } 4.402 + return (long)(sec * 1000.0); 4.403 +} 4.404 + 4.405 +static void print_hierarchy(const aiNode *node) 4.406 +{ 4.407 + static int lvl; 4.408 + static int lvlopen[256]; 4.409 + 4.410 + for(int i=0; i<lvl; i++) { 4.411 + putchar(' '); 4.412 + if(lvlopen[i]) { 4.413 + putchar(i >= lvl - 1 ? '+' : '|'); 4.414 + } else { 4.415 + putchar(i >= lvl - 1 ? '+' : ' '); 4.416 + } 4.417 + } 4.418 + info_log("- \"%s\"\n", node->mName.data); 4.419 + 4.420 + lvlopen[lvl] = 1; 4.421 + 4.422 + lvl++; 4.423 + for(unsigned int i=0; i<node->mNumChildren; i++) { 4.424 + if(i == node->mNumChildren - 1) { 4.425 + lvlopen[lvl - 1] = 0; 4.426 + } 4.427 + print_hierarchy(node->mChildren[i]); 4.428 + } 4.429 + lvl--; 4.430 +} 4.431 + 4.432 +#else // !defined USE_ASSIMP 4.433 + 4.434 +bool load_ass(Scene *scn, const char *fname) 4.435 +{ 4.436 + error_log("load_ass: assimp support not compiled in\n"); 4.437 + return false; 4.438 +} 4.439 + 4.440 +#endif
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/assload.h Thu Nov 14 05:27:09 2013 +0200 5.3 @@ -0,0 +1,9 @@ 5.4 +#ifndef ASSLOAD_H_ 5.5 +#define ASSLOAD_H_ 5.6 + 5.7 +#include <vector> 5.8 +#include "scene.h" 5.9 + 5.10 +bool load_ass(Scene *scn, const char *fname); 5.11 + 5.12 +#endif // ASSLOAD_H_
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/curve.cc Thu Nov 14 05:27:09 2013 +0200 6.3 @@ -0,0 +1,316 @@ 6.4 +#include <float.h> 6.5 +#include <assert.h> 6.6 +#include "curve.h" 6.7 +#include "opengl.h" 6.8 +#include "shader.h" 6.9 +#include "logger.h" 6.10 + 6.11 +#define DEF_THICKNESS 0.075 6.12 +#define DEF_SEGM_SUB 3 6.13 +#define DEF_RING_SUB 6 6.14 + 6.15 +Curve::Curve() 6.16 +{ 6.17 + thickness = DEF_THICKNESS; 6.18 + mesh_valid = false; 6.19 + lengths_valid = false; 6.20 + 6.21 + bbox_valid = false; 6.22 + 6.23 + segm_subdiv = DEF_SEGM_SUB; 6.24 + ring_subdiv = DEF_RING_SUB; 6.25 +} 6.26 + 6.27 +Curve::Curve(const Vector3 *points, int num_points) 6.28 +{ 6.29 + thickness = DEF_THICKNESS; 6.30 + mesh_valid = false; 6.31 + lengths_valid = false; 6.32 + 6.33 + bbox_valid = false; 6.34 + 6.35 + segm_subdiv = DEF_SEGM_SUB; 6.36 + ring_subdiv = DEF_RING_SUB; 6.37 + 6.38 + for(int i=0; i<num_points; i++) { 6.39 + add_point(points[i]); 6.40 + } 6.41 +} 6.42 + 6.43 +Curve::Curve(const Vector2 *points, int num_points) 6.44 +{ 6.45 + thickness = DEF_THICKNESS; 6.46 + mesh_valid = false; 6.47 + lengths_valid = false; 6.48 + 6.49 + bbox_valid = false; 6.50 + 6.51 + segm_subdiv = DEF_SEGM_SUB; 6.52 + ring_subdiv = DEF_RING_SUB; 6.53 + 6.54 + for(int i=0; i<num_points; i++) { 6.55 + add_point(Vector3(points[i].x, points[i].y, 0.0)); 6.56 + } 6.57 +} 6.58 + 6.59 +void Curve::set_name(const char *name) 6.60 +{ 6.61 + this->name = name; 6.62 +} 6.63 + 6.64 +const char *Curve::get_name() const 6.65 +{ 6.66 + return name.c_str(); 6.67 +} 6.68 + 6.69 +bool Curve::empty() const 6.70 +{ 6.71 + return cv.empty(); 6.72 +} 6.73 + 6.74 +void Curve::set_thickness(float thickness) 6.75 +{ 6.76 + this->thickness = thickness; 6.77 +} 6.78 + 6.79 +void Curve::set_subdiv(int seg, int ring) 6.80 +{ 6.81 + if(seg < 1) seg = 1; 6.82 + if(ring < 3) ring = 3; 6.83 + 6.84 + segm_subdiv = seg; 6.85 + ring_subdiv = ring; 6.86 +} 6.87 + 6.88 +void Curve::clear() 6.89 +{ 6.90 + mesh_valid = false; 6.91 + lengths_valid = false; 6.92 + bbox_valid = false; 6.93 + cv.clear(); 6.94 +} 6.95 + 6.96 +void Curve::add_point(const Vector3 &pt) 6.97 +{ 6.98 + cv.push_back(pt); 6.99 + mesh_valid = false; 6.100 + lengths_valid = false; 6.101 + bbox_valid = false; 6.102 +} 6.103 + 6.104 +Vector3 &Curve::get_point(int idx) 6.105 +{ 6.106 + mesh_valid = false; 6.107 + lengths_valid = false; 6.108 + bbox_valid = false; 6.109 + return cv[idx]; 6.110 +} 6.111 + 6.112 +const Vector3 &Curve::get_point(int idx) const 6.113 +{ 6.114 + return cv[idx]; 6.115 +} 6.116 + 6.117 +int Curve::get_count() const 6.118 +{ 6.119 + return (int)cv.size(); 6.120 +} 6.121 + 6.122 +Vector3 &Curve::operator[] (int idx) 6.123 +{ 6.124 + return get_point(idx); 6.125 +} 6.126 + 6.127 +const Vector3 &Curve::operator[] (int idx) const 6.128 +{ 6.129 + return get_point(idx); 6.130 +} 6.131 + 6.132 +void Curve::get_bbox(Vector3 *bbmin, Vector3 *bbmax) const 6.133 +{ 6.134 + if(!bbox_valid) { 6.135 + this->bbmin = Vector3(FLT_MAX, FLT_MAX, FLT_MAX); 6.136 + this->bbmax = -this->bbmin; 6.137 + 6.138 + for(size_t i=0; i<cv.size(); i++) { 6.139 + for(int j=0; j<3; j++) { 6.140 + if(cv[i][j] < this->bbmin[j]) { 6.141 + this->bbmin[j] = cv[i][j]; 6.142 + } 6.143 + if(cv[i][j] > this->bbmax[j]) { 6.144 + this->bbmax[j] = cv[i][j]; 6.145 + } 6.146 + } 6.147 + } 6.148 + bbox_valid = true; 6.149 + } 6.150 + 6.151 + if(bbmin) *bbmin = this->bbmin; 6.152 + if(bbmax) *bbmax = this->bbmax; 6.153 +} 6.154 + 6.155 +void Curve::normalize() 6.156 +{ 6.157 + get_bbox(0, 0); // force validation of the bounding box 6.158 + 6.159 + float len = (bbmax - bbmin).length() * 0.5; 6.160 + if(len == 0.0) { 6.161 + return; 6.162 + } 6.163 + 6.164 + for(size_t i=0; i<cv.size(); i++) { 6.165 + get_point(i) /= len; 6.166 + } 6.167 +} 6.168 + 6.169 +Vector3 Curve::get_pos(float t) const 6.170 +{ 6.171 + if(cv.empty()) { 6.172 + return Vector3(0, 0, 0); 6.173 + } 6.174 + if(cv.size() == 1 || t <= 0.0) { 6.175 + return cv[0]; 6.176 + } 6.177 + if(t >= 1.0) { 6.178 + return cv.back(); 6.179 + } 6.180 + 6.181 + t = reparametrize(t); 6.182 + 6.183 + int numcv = (int)cv.size(); 6.184 + int idx0 = t * (numcv - 1); 6.185 + int idx1 = idx0 + 1; 6.186 + 6.187 + int idx_prev = idx0 <= 0 ? idx0 : idx0 - 1; 6.188 + int idx_next = idx1 >= numcv - 1 ? idx1 : idx1 + 1; 6.189 + 6.190 + float dt = 1.0 / (float)(numcv - 1); 6.191 + 6.192 + float t0 = (float)idx0 * dt; 6.193 + float t1 = (float)idx1 * dt; 6.194 + 6.195 + t = (t - t0) / (t1 - t0); 6.196 + if(t < 0.0) t = 0.0; 6.197 + if(t > 1.0) t = 1.0; 6.198 + 6.199 + //return catmull_rom_spline(cv[idx_prev], cv[idx0], cv[idx1], cv[idx_next], t); 6.200 + return bspline(cv[idx_prev], cv[idx0], cv[idx1], cv[idx_next], t); 6.201 +} 6.202 + 6.203 +Vector3 Curve::operator() (float t) const 6.204 +{ 6.205 + return get_pos(t); 6.206 +} 6.207 + 6.208 +void Curve::draw() const 6.209 +{ 6.210 + update_mesh(); 6.211 + if(!mesh_valid) { 6.212 + return; 6.213 + } 6.214 + 6.215 + mesh.draw(); 6.216 +} 6.217 + 6.218 + 6.219 +float Curve::reparametrize(float t) const 6.220 +{ 6.221 + calc_cvlengths(); 6.222 + return t; // TODO 6.223 +} 6.224 + 6.225 +void Curve::calc_cvlengths() const 6.226 +{ 6.227 + if(lengths_valid || cv.empty()) { 6.228 + return; 6.229 + } 6.230 + 6.231 + length.clear(); 6.232 + length.resize(cv.size()); 6.233 + 6.234 + length[0] = 0; 6.235 + for(size_t i=1; i<cv.size(); i++) { 6.236 + length[i] = length[i - 1] + (cv[i] - cv[i - 1]).length(); 6.237 + } 6.238 + 6.239 + lengths_valid = true; 6.240 +} 6.241 + 6.242 +void Curve::update_mesh() const 6.243 +{ 6.244 + if(mesh_valid) return; 6.245 + 6.246 + if(cv.size() < 2) { 6.247 + return; 6.248 + } 6.249 + 6.250 + mesh.clear(); 6.251 + 6.252 + int nsub = segm_subdiv * (cv.size() - 1); 6.253 + int num_rings = nsub + 1; 6.254 + 6.255 + int num_verts = ring_subdiv * num_rings; 6.256 + int num_quads = ring_subdiv * nsub; 6.257 + int num_tri = num_quads * 2; 6.258 + int num_idx = num_tri * 3; 6.259 + 6.260 + float *varr = mesh.set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts); 6.261 + float *narr = mesh.set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts); 6.262 + float *tcarr = mesh.set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts); 6.263 + unsigned int *idxarr = mesh.set_index_data(num_idx); 6.264 + 6.265 + float t = 0.0; 6.266 + float dt = 1.0 / (float)(num_rings - 1); 6.267 + 6.268 + for(int i=0; i<num_rings; i++) { 6.269 + Vector3 p = get_pos(t); 6.270 + Vector3 dir = (get_pos(t + dt) - p).normalized(); 6.271 + 6.272 + Vector3 up = Vector3(0, 0, 1); 6.273 + float updotdir = dot_product(up, dir); 6.274 + if(1.0 - fabs(updotdir) < 1e-4) { 6.275 + up = Vector3(0, 1, 0); 6.276 + } 6.277 + Vector3 right = cross_product(up, dir).normalized(); 6.278 + up = cross_product(dir, right); 6.279 + 6.280 + for(int j=0; j<ring_subdiv; j++) { 6.281 + float u = (float)j / (float)ring_subdiv * M_PI * 2.0; 6.282 + Quaternion qrot(dir, u); 6.283 + Vector3 v = p + right.transformed(qrot) * thickness; 6.284 + 6.285 + *varr++ = v.x; 6.286 + *varr++ = v.y; 6.287 + *varr++ = v.z; 6.288 + 6.289 + Vector3 norm = (v - p).normalized(); 6.290 + *narr++ = norm.x; 6.291 + *narr++ = norm.y; 6.292 + *narr++ = norm.z; 6.293 + 6.294 + *tcarr++ = u; 6.295 + *tcarr++ = t; 6.296 + 6.297 + if(i < nsub) { 6.298 + int quad = i * ring_subdiv + j; 6.299 + 6.300 + int v0 = quad; 6.301 + int v1 = i * ring_subdiv + ((j + 1) % ring_subdiv); 6.302 + int v2 = (i + 1) * ring_subdiv + ((j + 1) % ring_subdiv); 6.303 + int v3 = (i + 1) * ring_subdiv + j; 6.304 + 6.305 + idxarr[quad * 6] = v0; 6.306 + idxarr[quad * 6 + 1] = v1; 6.307 + idxarr[quad * 6 + 2] = v2; 6.308 + 6.309 + idxarr[quad * 6 + 3] = v0; 6.310 + idxarr[quad * 6 + 4] = v2; 6.311 + idxarr[quad * 6 + 5] = v3; 6.312 + } 6.313 + } 6.314 + 6.315 + t += dt; 6.316 + } 6.317 + 6.318 + mesh_valid = true; 6.319 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/curve.h Thu Nov 14 05:27:09 2013 +0200 7.3 @@ -0,0 +1,64 @@ 7.4 +#ifndef CURVE_H_ 7.5 +#define CURVE_H_ 7.6 + 7.7 +#include <string> 7.8 +#include <vector> 7.9 +#include "vmath/vmath.h" 7.10 +#include "mesh.h" 7.11 + 7.12 +class Curve { 7.13 +private: 7.14 + std::string name; 7.15 + 7.16 + std::vector<Vector3> cv; 7.17 + float thickness; 7.18 + 7.19 + int segm_subdiv, ring_subdiv; 7.20 + 7.21 + /// normalized arc-lengths of each control vertex from the beginning 7.22 + mutable std::vector<float> length; 7.23 + mutable bool lengths_valid; 7.24 + 7.25 + mutable Vector3 bbmin, bbmax; 7.26 + mutable bool bbox_valid; 7.27 + 7.28 + mutable Mesh mesh; 7.29 + mutable bool mesh_valid; 7.30 + 7.31 + float reparametrize(float t) const; 7.32 + 7.33 + void calc_cvlengths() const; 7.34 + void update_mesh() const; 7.35 + 7.36 +public: 7.37 + Curve(); 7.38 + Curve(const Vector3 *points, int num_points); 7.39 + Curve(const Vector2 *points, int num_points); 7.40 + 7.41 + void set_name(const char *name); 7.42 + const char *get_name() const; 7.43 + 7.44 + bool empty() const; 7.45 + 7.46 + void set_thickness(float thickness); 7.47 + void set_subdiv(int seg, int ring); 7.48 + 7.49 + void clear(); 7.50 + void add_point(const Vector3 &pt); 7.51 + Vector3 &get_point(int idx); 7.52 + const Vector3 &get_point(int idx) const; 7.53 + int get_count() const; 7.54 + 7.55 + Vector3 &operator[] (int idx); 7.56 + const Vector3 &operator[] (int idx) const; 7.57 + 7.58 + void get_bbox(Vector3 *bbmin, Vector3 *bbmax) const; 7.59 + void normalize(); 7.60 + 7.61 + Vector3 get_pos(float t) const; 7.62 + Vector3 operator() (float t) const; 7.63 + 7.64 + void draw() const; 7.65 +}; 7.66 + 7.67 +#endif // CURVE_H_
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/src/curveload.cc Thu Nov 14 05:27:09 2013 +0200 8.3 @@ -0,0 +1,195 @@ 8.4 +#include <string> 8.5 +#include <assert.h> 8.6 +#include <stdint.h> 8.7 +#include "curveload.h" 8.8 +#include "3dschunks.h" 8.9 +#include "logger.h" 8.10 + 8.11 +static uint32_t read_counter; 8.12 + 8.13 +struct ChunkHeader { 8.14 + ChunkID id; 8.15 + uint32_t size; 8.16 +}; 8.17 + 8.18 +#define HEADER_SIZE 6 8.19 + 8.20 +// local function prototypes 8.21 +static uint8_t read_byte(FILE *file); 8.22 +static uint16_t read_int16(FILE *file); 8.23 +static uint32_t read_int32(FILE *file); 8.24 +static float read_float(FILE *file); 8.25 +static Vector3 read_vector(FILE *file, bool flip_yz = false); 8.26 +static std::string read_string(FILE *file); 8.27 +static ChunkHeader read_chunk_header(FILE *file); 8.28 +static void skip_chunk(FILE *file, const ChunkHeader &chunk); 8.29 +static Curve *read_curve(FILE *file, const ChunkHeader &ch); 8.30 + 8.31 +static bool eof; 8.32 + 8.33 +bool load_curves(Scene *scn, const char *fname) 8.34 +{ 8.35 + FILE *file = fopen(fname, "rb"); 8.36 + if(!file) { 8.37 + error_log("failed to open curves scene file: %s\n", fname); 8.38 + return false; 8.39 + } 8.40 + eof = false; 8.41 + 8.42 + ChunkHeader chunk; 8.43 + 8.44 + chunk = read_chunk_header(file); 8.45 + if(chunk.id != Chunk_3DSMain) { 8.46 + fclose(file); 8.47 + return false; 8.48 + } 8.49 + 8.50 + while(!eof) { 8.51 + chunk = read_chunk_header(file); 8.52 + 8.53 + Curve *curve; 8.54 + 8.55 + switch(chunk.id) { 8.56 + case Chunk_Main_3DEditor: 8.57 + break; // dont skip 8.58 + 8.59 + case Chunk_Edit_Object: 8.60 + if((curve = read_curve(file, chunk))) { 8.61 + scn->curves.push_back(curve); 8.62 + } 8.63 + break; 8.64 + 8.65 + default: 8.66 + skip_chunk(file, chunk); 8.67 + } 8.68 + } 8.69 + 8.70 + fclose(file); 8.71 + return true; 8.72 +} 8.73 + 8.74 +static uint8_t read_byte(FILE *fp) { 8.75 + uint8_t v; 8.76 + if(fread(&v, 1, 1, fp) <= 0) { 8.77 + eof = true; 8.78 + return 0; 8.79 + } 8.80 + read_counter++; 8.81 + return v; 8.82 +} 8.83 + 8.84 +static uint16_t read_int16(FILE *fp) { 8.85 + uint16_t v; 8.86 + if(fread(&v, 2, 1, fp) <= 0) { 8.87 + eof = true; 8.88 + return 0; 8.89 + } 8.90 + read_counter += 2; 8.91 + return v; 8.92 +} 8.93 + 8.94 +static uint32_t read_int32(FILE *fp) { 8.95 + uint32_t v; 8.96 + if(fread(&v, 4, 1, fp) <= 0) { 8.97 + eof = true; 8.98 + return 0; 8.99 + } 8.100 + read_counter += 4; 8.101 + return v; 8.102 +} 8.103 + 8.104 +static float read_float(FILE *fp) 8.105 +{ 8.106 + int32_t tmp = read_int32(fp); 8.107 + return *((float*)&tmp); 8.108 +} 8.109 + 8.110 +static Vector3 read_vector(FILE *file, bool flip_yz) 8.111 +{ 8.112 + Vector3 vector; 8.113 + vector.x = read_float(file); 8.114 + if(!flip_yz) vector.y = read_float(file); 8.115 + vector.z = read_float(file); 8.116 + if(flip_yz) vector.y = read_float(file); 8.117 + return vector; 8.118 +} 8.119 + 8.120 +static std::string read_string(FILE *file) 8.121 +{ 8.122 + std::string str; 8.123 + char c; 8.124 + while((c = (char)read_byte(file))) { 8.125 + str.push_back(c); 8.126 + } 8.127 + read_counter++; 8.128 + 8.129 + return str; 8.130 +} 8.131 + 8.132 +static ChunkHeader read_chunk_header(FILE *file) 8.133 +{ 8.134 + ChunkHeader chunk; 8.135 + chunk.id = (ChunkID)read_int16(file); 8.136 + chunk.size = read_int32(file); 8.137 + return chunk; 8.138 +} 8.139 + 8.140 +static void skip_chunk(FILE *file, const ChunkHeader &chunk) 8.141 +{ 8.142 + if(eof) return; 8.143 + fseek(file, chunk.size - HEADER_SIZE, SEEK_CUR); 8.144 + read_counter += chunk.size - HEADER_SIZE; 8.145 +} 8.146 + 8.147 +static Curve *read_curve(FILE *file, const ChunkHeader &ch) 8.148 +{ 8.149 + read_counter = HEADER_SIZE; // reset the global read counter 8.150 + 8.151 + std::string name = read_string(file); 8.152 + 8.153 + ChunkHeader chunk; 8.154 + chunk = read_chunk_header(file); 8.155 + if(chunk.id == Chunk_Obj_TriMesh) { 8.156 + // object is a trimesh... load it 8.157 + Vector3 *varray = 0; 8.158 + uint32_t vertex_count = 0; 8.159 + 8.160 + uint32_t obj_chunk_size = ch.size; 8.161 + 8.162 + while(read_counter < obj_chunk_size) { // make sure we only read subchunks of this object chunk 8.163 + chunk = read_chunk_header(file); 8.164 + 8.165 + switch(chunk.id) { 8.166 + case Chunk_TriMesh_VertexList: 8.167 + vertex_count = (uint32_t)read_int16(file); 8.168 + varray = new Vector3[vertex_count]; 8.169 + 8.170 + for(uint32_t i=0; i<vertex_count; i++) { 8.171 + varray[i] = read_vector(file); 8.172 + } 8.173 + 8.174 + break; 8.175 + 8.176 + case Chunk_TriMesh_FaceDesc: 8.177 + // it is a real object not a curve since it has triangles 8.178 + delete [] varray; 8.179 + varray = 0; 8.180 + break; 8.181 + 8.182 + default: 8.183 + skip_chunk(file, chunk); 8.184 + } 8.185 + } 8.186 + 8.187 + if(varray) { 8.188 + Curve *curve = new Curve; 8.189 + curve->set_name(name.c_str()); 8.190 + for(uint32_t i=0; i<vertex_count; i++) { 8.191 + curve->add_point(varray[i]); 8.192 + } 8.193 + return curve; 8.194 + } 8.195 + } 8.196 + 8.197 + return 0; 8.198 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/src/curveload.h Thu Nov 14 05:27:09 2013 +0200 9.3 @@ -0,0 +1,8 @@ 9.4 +#ifndef CURVELOAD_H_ 9.5 +#define CURVELOAD_H_ 9.6 + 9.7 +#include "scene.h" 9.8 + 9.9 +bool load_curves(Scene *scn, const char *fname); 9.10 + 9.11 +#endif // CURVELOAD_H_
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/src/datapath.cc Thu Nov 14 05:27:09 2013 +0200 10.3 @@ -0,0 +1,67 @@ 10.4 +#include <stdio.h> 10.5 +#include <set> 10.6 +#include <string> 10.7 +#include "logger.h" 10.8 +#include "datapath.h" 10.9 + 10.10 +static std::set<std::string> paths; 10.11 + 10.12 +void add_data_path(const char *path) 10.13 +{ 10.14 + paths.insert(path); 10.15 +} 10.16 + 10.17 +#ifndef TARGET_IPHONE 10.18 +std::string datafile_path(const char *fname) 10.19 +{ 10.20 + std::string res; 10.21 + if(!fname) { 10.22 + return res; 10.23 + } 10.24 + 10.25 + std::set<std::string>::const_iterator it = paths.begin(); 10.26 + while(it != paths.end()) { 10.27 + const std::string &path = *it++; 10.28 + res = path + "/" + std::string(fname); 10.29 + FILE *fp = fopen(res.c_str(), "r"); 10.30 + if(fp) { 10.31 + fclose(fp); 10.32 + return res; 10.33 + } 10.34 + } 10.35 + 10.36 + // It's not found. Return the name itself just in case it's right here 10.37 + return std::string(fname); 10.38 +} 10.39 +#else 10.40 +#include <CoreFoundation/CoreFoundation.h> 10.41 + 10.42 +std::string datafile_path(const char *fname) 10.43 +{ 10.44 + std::string res; 10.45 + if(!fname) { 10.46 + return res; 10.47 + } 10.48 + 10.49 + CFBundleRef bundle; 10.50 + CFURLRef url; 10.51 + CFStringRef cfname; 10.52 + 10.53 + cfname = CFStringCreateWithCString(0, fname, kCFStringEncodingASCII); 10.54 + 10.55 + bundle = CFBundleGetMainBundle(); 10.56 + if(!(url = CFBundleCopyResourceURL(bundle, cfname, 0, 0))) { 10.57 + CFRelease(cfname); 10.58 + return fname; 10.59 + } 10.60 + CFRelease(cfname); 10.61 + 10.62 + char path[1024]; 10.63 + if(!CFURLGetFileSystemRepresentation(url, 1, (unsigned char*)path, sizeof path)) { 10.64 + CFRelease(url); 10.65 + return fname; 10.66 + } 10.67 + CFRelease(url); 10.68 + return std::string(path); 10.69 +} 10.70 +#endif
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/src/datapath.h Thu Nov 14 05:27:09 2013 +0200 11.3 @@ -0,0 +1,10 @@ 11.4 +#ifndef DATAPATH_H_ 11.5 +#define DATAPATH_H_ 11.6 + 11.7 +#include <string> 11.8 + 11.9 +void add_data_path(const char *path); 11.10 + 11.11 +std::string datafile_path(const char *fname); 11.12 + 11.13 +#endif // DATAPATH_H_
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/src/dataset.h Thu Nov 14 05:27:09 2013 +0200 12.3 @@ -0,0 +1,44 @@ 12.4 +/** DataSet is a generic resource database with fast O(logn) lookups by name 12.5 + * it can be used for texture managers, mesh managers, sound effect managers etc 12.6 + * 12.7 + * The constructor takes a load function and a destructor function to be called 12.8 + * when a nonexistent resource is requested and needs to be loaded, and when 12.9 + * the DataSet is destroyed. The destructor is optional and can be set to null 12.10 + * if not needed. 12.11 + * 12.12 + * Requesting a resource works by simply calling get, example: 12.13 + * ---------------------------------------------------------- 12.14 + * \code 12.15 + * Texture *load_texture(const char *fname); 12.16 + * void free_texture(Texture *tex); 12.17 + * 12.18 + * DataSet<Texture*> texman(load_texture, free_texture); 12.19 + * Texture *foo = texman.get("foo.png"); 12.20 + * \endcode 12.21 + */ 12.22 +#ifndef DATASET_H_ 12.23 +#define DATASET_H_ 12.24 + 12.25 +#include <string> 12.26 +#include <map> 12.27 + 12.28 +template <typename T> 12.29 +class DataSet { 12.30 +protected: 12.31 + mutable std::map<std::string, T> data; 12.32 + 12.33 + T (*load)(const char*); 12.34 + void (*destroy)(T); 12.35 + 12.36 +public: 12.37 + DataSet(T (*load_func)(const char*), void (*destr_func)(T) = 0); 12.38 + ~DataSet(); 12.39 + 12.40 + void clear(); 12.41 + 12.42 + T get(const char *name) const; 12.43 +}; 12.44 + 12.45 +#include "dataset.inl" 12.46 + 12.47 +#endif // DATASET_H_
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/src/dataset.inl Thu Nov 14 05:27:09 2013 +0200 13.3 @@ -0,0 +1,56 @@ 13.4 +#include <stdio.h> 13.5 +#include <string.h> 13.6 +#include "datapath.h" 13.7 + 13.8 +template <typename T> 13.9 +DataSet<T>::DataSet(T (*load_func)(const char*), void (*destr_func)(T)) 13.10 +{ 13.11 + load = load_func; 13.12 + destroy = destr_func; 13.13 +} 13.14 + 13.15 +template <typename T> 13.16 +DataSet<T>::~DataSet() 13.17 +{ 13.18 + clear(); 13.19 +} 13.20 + 13.21 +template <typename T> 13.22 +void DataSet<T>::clear() 13.23 +{ 13.24 + if(destroy) { 13.25 + typename std::map<std::string, T>::iterator it = data.begin(); 13.26 + while(it != data.end()) { 13.27 + destroy(it++->second); 13.28 + } 13.29 + } 13.30 + data.clear(); 13.31 +} 13.32 + 13.33 +template <typename T> 13.34 +T DataSet<T>::get(const char *name) const 13.35 +{ 13.36 + typename std::map<std::string, T>::const_iterator iter = data.find(name); 13.37 + if(iter != data.end()) { 13.38 + return iter->second; 13.39 + } 13.40 + 13.41 + const char *fname, *slash; 13.42 + if((slash = strrchr(name, '/'))) { 13.43 + fname = slash + 1; 13.44 + } else { 13.45 + fname = name; 13.46 + } 13.47 + 13.48 + std::string path = datafile_path(fname); 13.49 + if(path.empty()) { 13.50 + fprintf(stderr, "can't find data file: %s\n", name); 13.51 + return 0; 13.52 + } 13.53 + 13.54 + T res = load(path.c_str()); 13.55 + if(res) { 13.56 + data[name] = res; 13.57 + } 13.58 + return res; 13.59 +}
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/src/geom.cc Thu Nov 14 05:27:09 2013 +0200 14.3 @@ -0,0 +1,252 @@ 14.4 +#include <algorithm> 14.5 +#include <float.h> 14.6 +#include "geom.h" 14.7 +#include "logger.h" 14.8 + 14.9 +GeomObject::~GeomObject() 14.10 +{ 14.11 +} 14.12 + 14.13 + 14.14 +Sphere::Sphere() 14.15 +{ 14.16 + radius = 1.0; 14.17 +} 14.18 + 14.19 +Sphere::Sphere(const Vector3 ¢, float radius) 14.20 + : center(cent) 14.21 +{ 14.22 + this->radius = radius; 14.23 +} 14.24 + 14.25 +void Sphere::set_union(const GeomObject *obj1, const GeomObject *obj2) 14.26 +{ 14.27 + const Sphere *sph1 = dynamic_cast<const Sphere*>(obj1); 14.28 + const Sphere *sph2 = dynamic_cast<const Sphere*>(obj2); 14.29 + 14.30 + if(!sph1 || !sph2) { 14.31 + error_log("Sphere::set_union: arguments must be spheres"); 14.32 + return; 14.33 + } 14.34 + 14.35 + float dist = (sph1->center - sph2->center).length(); 14.36 + float surf_dist = dist - (sph1->radius + sph2->radius); 14.37 + float d1 = sph1->radius + surf_dist / 2.0; 14.38 + float d2 = sph2->radius + surf_dist / 2.0; 14.39 + float t = d1 / (d1 + d2); 14.40 + 14.41 + if(t < 0.0) t = 0.0; 14.42 + if(t > 1.0) t = 1.0; 14.43 + 14.44 + center = sph1->center * t + sph2->center * (1.0 - t); 14.45 + radius = std::max(dist * t + sph2->radius, dist * (1.0f - t) + sph1->radius); 14.46 +} 14.47 + 14.48 +void Sphere::set_intersection(const GeomObject *obj1, const GeomObject *obj2) 14.49 +{ 14.50 + error_log("Sphere::intersection undefined\n"); 14.51 +} 14.52 + 14.53 +bool Sphere::intersect(const Ray &ray, HitPoint *hit) const 14.54 +{ 14.55 + float a = dot_product(ray.dir, ray.dir); 14.56 + float b = 2.0 * ray.dir.x * (ray.origin.x - center.x) + 14.57 + 2.0 * ray.dir.y * (ray.origin.y - center.y) + 14.58 + 2.0 * ray.dir.z * (ray.origin.z - center.z); 14.59 + float c = dot_product(ray.origin, ray.origin) + dot_product(center, center) - 14.60 + 2.0 * dot_product(ray.origin, center) - radius * radius; 14.61 + 14.62 + float discr = b * b - 4.0 * a * c; 14.63 + if(discr < 1e-4) { 14.64 + return false; 14.65 + } 14.66 + 14.67 + float sqrt_discr = sqrt(discr); 14.68 + float t0 = (-b + sqrt_discr) / (2.0 * a); 14.69 + float t1 = (-b - sqrt_discr) / (2.0 * a); 14.70 + 14.71 + if(t0 < 1e-4) 14.72 + t0 = t1; 14.73 + if(t1 < 1e-4) 14.74 + t1 = t0; 14.75 + 14.76 + float t = t0 < t1 ? t0 : t1; 14.77 + if(t < 1e-4) { 14.78 + return false; 14.79 + } 14.80 + 14.81 + // fill the HitPoint structure 14.82 + if(hit) { 14.83 + hit->obj = this; 14.84 + hit->dist = t; 14.85 + hit->pos = ray.origin + ray.dir * t; 14.86 + hit->normal = (hit->pos - center) / radius; 14.87 + } 14.88 + return true; 14.89 +} 14.90 + 14.91 + 14.92 +AABox::AABox() 14.93 +{ 14.94 +} 14.95 + 14.96 +AABox::AABox(const Vector3 &vmin, const Vector3 &vmax) 14.97 + : min(vmin), max(vmax) 14.98 +{ 14.99 +} 14.100 + 14.101 +void AABox::set_union(const GeomObject *obj1, const GeomObject *obj2) 14.102 +{ 14.103 + const AABox *box1 = dynamic_cast<const AABox*>(obj1); 14.104 + const AABox *box2 = dynamic_cast<const AABox*>(obj2); 14.105 + 14.106 + if(!box1 || !box2) { 14.107 + error_log("AABox::set_union: arguments must be AABoxes too\n"); 14.108 + return; 14.109 + } 14.110 + 14.111 + min.x = std::min(box1->min.x, box2->min.x); 14.112 + min.y = std::min(box1->min.y, box2->min.y); 14.113 + min.z = std::min(box1->min.z, box2->min.z); 14.114 + 14.115 + max.x = std::max(box1->max.x, box2->max.x); 14.116 + max.y = std::max(box1->max.y, box2->max.y); 14.117 + max.z = std::max(box1->max.z, box2->max.z); 14.118 +} 14.119 + 14.120 +void AABox::set_intersection(const GeomObject *obj1, const GeomObject *obj2) 14.121 +{ 14.122 + const AABox *box1 = dynamic_cast<const AABox*>(obj1); 14.123 + const AABox *box2 = dynamic_cast<const AABox*>(obj2); 14.124 + 14.125 + if(!box1 || !box2) { 14.126 + error_log("AABox::set_intersection: arguments must be AABoxes too\n"); 14.127 + return; 14.128 + } 14.129 + 14.130 + for(int i=0; i<3; i++) { 14.131 + min[i] = std::max(box1->min[i], box2->min[i]); 14.132 + max[i] = std::min(box1->max[i], box2->max[i]); 14.133 + 14.134 + if(max[i] < min[i]) { 14.135 + max[i] = min[i]; 14.136 + } 14.137 + } 14.138 +} 14.139 + 14.140 +bool AABox::intersect(const Ray &ray, HitPoint *hit) const 14.141 +{ 14.142 + Vector3 param[2] = {min, max}; 14.143 + Vector3 inv_dir(1.0 / ray.dir.x, 1.0 / ray.dir.y, 1.0 / ray.dir.z); 14.144 + int sign[3] = {inv_dir.x < 0, inv_dir.y < 0, inv_dir.z < 0}; 14.145 + 14.146 + float tmin = (param[sign[0]].x - ray.origin.x) * inv_dir.x; 14.147 + float tmax = (param[1 - sign[0]].x - ray.origin.x) * inv_dir.x; 14.148 + float tymin = (param[sign[1]].y - ray.origin.y) * inv_dir.y; 14.149 + float tymax = (param[1 - sign[1]].y - ray.origin.y) * inv_dir.y; 14.150 + 14.151 + if(tmin > tymax || tymin > tmax) { 14.152 + return false; 14.153 + } 14.154 + if(tymin > tmin) { 14.155 + tmin = tymin; 14.156 + } 14.157 + if(tymax < tmax) { 14.158 + tmax = tymax; 14.159 + } 14.160 + 14.161 + float tzmin = (param[sign[2]].z - ray.origin.z) * inv_dir.z; 14.162 + float tzmax = (param[1 - sign[2]].z - ray.origin.z) * inv_dir.z; 14.163 + 14.164 + if(tmin > tzmax || tzmin > tmax) { 14.165 + return false; 14.166 + } 14.167 + if(tzmin > tmin) { 14.168 + tmin = tzmin; 14.169 + } 14.170 + if(tzmax < tmax) { 14.171 + tmax = tzmax; 14.172 + } 14.173 + 14.174 + float t = tmin < 1e-4 ? tmax : tmin; 14.175 + if(t >= 1e-4) { 14.176 + 14.177 + if(hit) { 14.178 + hit->obj = this; 14.179 + hit->dist = t; 14.180 + hit->pos = ray.origin + ray.dir * t; 14.181 + 14.182 + float min_dist = FLT_MAX; 14.183 + Vector3 offs = min + (max - min) / 2.0; 14.184 + Vector3 local_hit = hit->pos - offs; 14.185 + 14.186 + static const Vector3 axis[] = { 14.187 + Vector3(1, 0, 0), Vector3(0, 1, 0), Vector3(0, 0, 1) 14.188 + }; 14.189 + //int tcidx[][2] = {{2, 1}, {0, 2}, {0, 1}}; 14.190 + 14.191 + for(int i=0; i<3; i++) { 14.192 + float dist = fabs((max[i] - offs[i]) - fabs(local_hit[i])); 14.193 + if(dist < min_dist) { 14.194 + min_dist = dist; 14.195 + hit->normal = axis[i] * (local_hit[i] < 0.0 ? 1.0 : -1.0); 14.196 + //hit->texcoord = Vector2(hit->pos[tcidx[i][0]], hit->pos[tcidx[i][1]]); 14.197 + } 14.198 + } 14.199 + } 14.200 + return true; 14.201 + } 14.202 + return false; 14.203 + 14.204 +} 14.205 + 14.206 +Plane::Plane() 14.207 + : normal(0.0, 1.0, 0.0) 14.208 +{ 14.209 +} 14.210 + 14.211 +Plane::Plane(const Vector3 &p, const Vector3 &norm) 14.212 + : pt(p) 14.213 +{ 14.214 + normal = norm.normalized(); 14.215 +} 14.216 + 14.217 +Plane::Plane(const Vector3 &p1, const Vector3 &p2, const Vector3 &p3) 14.218 + : pt(p1) 14.219 +{ 14.220 + normal = cross_product(p2 - p1, p3 - p1).normalized(); 14.221 +} 14.222 + 14.223 +Plane::Plane(const Vector3 &normal, float dist) 14.224 +{ 14.225 + this->normal = normal.normalized(); 14.226 + pt = this->normal * dist; 14.227 +} 14.228 + 14.229 +void Plane::set_union(const GeomObject *obj1, const GeomObject *obj2) 14.230 +{ 14.231 + error_log("Plane::set_union undefined\n"); 14.232 +} 14.233 + 14.234 +void Plane::set_intersection(const GeomObject *obj1, const GeomObject *obj2) 14.235 +{ 14.236 + error_log("Plane::set_intersection undefined\n"); 14.237 +} 14.238 + 14.239 +bool Plane::intersect(const Ray &ray, HitPoint *hit) const 14.240 +{ 14.241 + float ndotdir = dot_product(normal, ray.dir); 14.242 + if(fabs(ndotdir) < 1e-4) { 14.243 + return false; 14.244 + } 14.245 + 14.246 + if(hit) { 14.247 + Vector3 ptdir = pt - ray.origin; 14.248 + float t = dot_product(normal, ptdir) / ndotdir; 14.249 + 14.250 + hit->pos = ray.origin + ray.dir * t; 14.251 + hit->normal = normal; 14.252 + hit->obj = this; 14.253 + } 14.254 + return true; 14.255 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/src/geom.h Thu Nov 14 05:27:09 2013 +0200 15.3 @@ -0,0 +1,67 @@ 15.4 +#ifndef GEOMOBJ_H_ 15.5 +#define GEOMOBJ_H_ 15.6 + 15.7 +#include "vmath/vmath.h" 15.8 + 15.9 +class GeomObject; 15.10 + 15.11 +struct HitPoint { 15.12 + float dist; //< parametric distance along the ray 15.13 + Vector3 pos; //< position of intersection (orig + dir * dist) 15.14 + Vector3 normal; //< normal at the point of intersection 15.15 + const void *obj; //< pointer to the intersected object 15.16 +}; 15.17 + 15.18 +class GeomObject { 15.19 +public: 15.20 + virtual ~GeomObject(); 15.21 + 15.22 + virtual void set_union(const GeomObject *obj1, const GeomObject *obj2) = 0; 15.23 + virtual void set_intersection(const GeomObject *obj1, const GeomObject *obj2) = 0; 15.24 + 15.25 + virtual bool intersect(const Ray &ray, HitPoint *hit = 0) const = 0; 15.26 +}; 15.27 + 15.28 +class Sphere : public GeomObject { 15.29 +public: 15.30 + Vector3 center; 15.31 + float radius; 15.32 + 15.33 + Sphere(); 15.34 + Sphere(const Vector3 ¢er, float radius); 15.35 + 15.36 + void set_union(const GeomObject *obj1, const GeomObject *obj2); 15.37 + void set_intersection(const GeomObject *obj1, const GeomObject *obj2); 15.38 + 15.39 + bool intersect(const Ray &ray, HitPoint *hit = 0) const; 15.40 +}; 15.41 + 15.42 +class AABox : public GeomObject { 15.43 +public: 15.44 + Vector3 min, max; 15.45 + 15.46 + AABox(); 15.47 + AABox(const Vector3 &min, const Vector3 &max); 15.48 + 15.49 + void set_union(const GeomObject *obj1, const GeomObject *obj2); 15.50 + void set_intersection(const GeomObject *obj1, const GeomObject *obj2); 15.51 + 15.52 + bool intersect(const Ray &ray, HitPoint *hit = 0) const; 15.53 +}; 15.54 + 15.55 +class Plane : public GeomObject { 15.56 +public: 15.57 + Vector3 pt, normal; 15.58 + 15.59 + Plane(); 15.60 + Plane(const Vector3 &pt, const Vector3 &normal); 15.61 + Plane(const Vector3 &p1, const Vector3 &p2, const Vector3 &p3); 15.62 + Plane(const Vector3 &normal, float dist); 15.63 + 15.64 + void set_union(const GeomObject *obj1, const GeomObject *obj2); 15.65 + void set_intersection(const GeomObject *obj1, const GeomObject *obj2); 15.66 + 15.67 + bool intersect(const Ray &ray, HitPoint *hit = 0) const; 15.68 +}; 15.69 + 15.70 +#endif // GEOMOBJ_H_
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/src/gfxutil.cc Thu Nov 14 05:27:09 2013 +0200 16.3 @@ -0,0 +1,64 @@ 16.4 +#include <assert.h> 16.5 +#include "gfxutil.h" 16.6 +#include "mesh.h" 16.7 +#include "meshgen.h" 16.8 +#include "texture.h" 16.9 +#include "shader.h" 16.10 +#include "sdrman.h" 16.11 +#include "opengl.h" 16.12 +#include "logger.h" 16.13 + 16.14 +void draw_rect(const Vector3 &v1, const Vector3 &v2, Texture2D *tex, ShaderProg *sdr) 16.15 +{ 16.16 + static ShaderProg *defsdr; 16.17 + 16.18 + if(!defsdr) { 16.19 + if(!(defsdr = get_sdrprog("defpost.v.glsl", "defpost.p.glsl"))) { 16.20 + static bool didlog; 16.21 + if(!didlog) { 16.22 + error_log("draw_rect: failed to load default shader\n"); 16.23 + didlog = true; 16.24 + } 16.25 + if(!sdr) { 16.26 + return; 16.27 + } 16.28 + } 16.29 + } 16.30 + 16.31 + 16.32 + if(tex) { 16.33 + set_texture(tex); 16.34 + } 16.35 + if(sdr) { 16.36 + sdr->bind(); 16.37 + } else { 16.38 + defsdr->bind(); 16.39 + 16.40 + assert(defsdr->get_attrib_location("attr_vertex") == MESH_ATTR_VERTEX); 16.41 + assert(defsdr->get_attrib_location("attr_texcoord") == MESH_ATTR_TEXCOORD); 16.42 + } 16.43 + 16.44 + 16.45 + float varr[] = { 16.46 + v1.x, v1.y, v1.z, v2.x, v1.y, v2.z, 16.47 + v2.x, v2.y, v2.z, v1.x, v2.y, v1.z 16.48 + }; 16.49 + static const float tarr[] = { 0, 0, 1, 0, 1, 1, 0, 1 }; 16.50 + static const unsigned int idxarr[] = {0, 1, 2, 0, 2, 3}; 16.51 + 16.52 + // disable VBOs if they are enabled 16.53 + glBindBuffer(GL_ARRAY_BUFFER, 0); 16.54 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 16.55 + 16.56 + glEnableVertexAttribArray(MESH_ATTR_VERTEX); 16.57 + glVertexAttribPointer(MESH_ATTR_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, varr); 16.58 + glEnableVertexAttribArray(MESH_ATTR_TEXCOORD); 16.59 + glVertexAttribPointer(MESH_ATTR_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, tarr); 16.60 + 16.61 + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, idxarr); 16.62 + 16.63 + glDisableVertexAttribArray(MESH_ATTR_VERTEX); 16.64 + glDisableVertexAttribArray(MESH_ATTR_TEXCOORD); 16.65 + 16.66 + set_texture(0); 16.67 +}
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/src/gfxutil.h Thu Nov 14 05:27:09 2013 +0200 17.3 @@ -0,0 +1,11 @@ 17.4 +#ifndef GFXUTIL_H_ 17.5 +#define GFXUTIL_H_ 17.6 + 17.7 +#include <vmath/vmath.h> 17.8 + 17.9 +class Texture2D; 17.10 +class ShaderProg; 17.11 + 17.12 +void draw_rect(const Vector3 &v1, const Vector3 &v2, Texture2D *tex = 0, ShaderProg *sdr = 0); 17.13 + 17.14 +#endif // GFXUTIL_H_
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/src/image.cc Thu Nov 14 05:27:09 2013 +0200 18.3 @@ -0,0 +1,192 @@ 18.4 +#include <string.h> 18.5 +#include "imago2.h" 18.6 +#include "image.h" 18.7 +#include "logger.h" 18.8 + 18.9 + 18.10 +static int pixel_elements(Image::Format fmt); 18.11 +static int elem_size(Image::Format fmt); 18.12 +static int pixel_size(Image::Format fmt); 18.13 + 18.14 +Image::Image() 18.15 +{ 18.16 + fmt = FMT_RGBA; 18.17 + width = height = 0; 18.18 + pixels = 0; 18.19 +} 18.20 + 18.21 +Image::~Image() 18.22 +{ 18.23 + delete [] (char*)pixels; 18.24 +} 18.25 + 18.26 +int Image::get_width() const 18.27 +{ 18.28 + return width; 18.29 +} 18.30 + 18.31 +int Image::get_height() const 18.32 +{ 18.33 + return height; 18.34 +} 18.35 + 18.36 +Image::Format Image::get_format() const 18.37 +{ 18.38 + return fmt; 18.39 +} 18.40 + 18.41 +bool Image::create(int x, int y, Format fmt) 18.42 +{ 18.43 + width = x; 18.44 + height = y; 18.45 + this->fmt = fmt; 18.46 + 18.47 + try { 18.48 + pixels = new char[x * y * pixel_size(fmt)]; 18.49 + } 18.50 + catch(...) { 18.51 + return false; 18.52 + } 18.53 + return true; 18.54 +} 18.55 + 18.56 +bool Image::set_pixels(int x, int y, void *pixels, Format fmt) 18.57 +{ 18.58 + if(!create(x, y, fmt)) { 18.59 + return false; 18.60 + } 18.61 + memcpy(this->pixels, pixels, x * y * pixel_size(fmt)); 18.62 + return true; 18.63 +} 18.64 + 18.65 +void *Image::get_pixels() const 18.66 +{ 18.67 + return pixels; 18.68 +} 18.69 + 18.70 +bool Image::load(const char *fname) 18.71 +{ 18.72 + struct img_pixmap pixmap; 18.73 + 18.74 + img_init(&pixmap); 18.75 + if(img_load(&pixmap, fname) == -1) { 18.76 + return false; 18.77 + } 18.78 + 18.79 + Format fmt; 18.80 + switch(pixmap.fmt) { 18.81 + case IMG_FMT_GREY8: 18.82 + fmt = FMT_GREY; 18.83 + break; 18.84 + case IMG_FMT_RGB24: 18.85 + fmt = FMT_RGB; 18.86 + break; 18.87 + case IMG_FMT_RGBA32: 18.88 + fmt = FMT_RGBA; 18.89 + break; 18.90 + case IMG_FMT_GREYF: 18.91 + fmt = FMT_GREY_FLOAT; 18.92 + break; 18.93 + case IMG_FMT_RGBF: 18.94 + fmt = FMT_RGB_FLOAT; 18.95 + break; 18.96 + case IMG_FMT_RGBAF: 18.97 + fmt = FMT_RGBA_FLOAT; 18.98 + break; 18.99 + default: 18.100 + img_destroy(&pixmap); 18.101 + return false; 18.102 + } 18.103 + 18.104 + if(!set_pixels(pixmap.width, pixmap.height, pixmap.pixels, fmt)) { 18.105 + img_destroy(&pixmap); 18.106 + return false; 18.107 + } 18.108 + img_destroy(&pixmap); 18.109 + return true; 18.110 +} 18.111 + 18.112 +bool Image::save(const char *fname) const 18.113 +{ 18.114 + struct img_pixmap pixmap; 18.115 + 18.116 + img_init(&pixmap); 18.117 + 18.118 + switch(fmt) { 18.119 + case FMT_GREY: 18.120 + pixmap.fmt = IMG_FMT_GREY8; 18.121 + break; 18.122 + case FMT_GREY_FLOAT: 18.123 + pixmap.fmt = IMG_FMT_GREYF; 18.124 + break; 18.125 + case FMT_RGB: 18.126 + pixmap.fmt = IMG_FMT_RGB24; 18.127 + break; 18.128 + case FMT_RGB_FLOAT: 18.129 + pixmap.fmt = IMG_FMT_RGBF; 18.130 + break; 18.131 + case FMT_RGBA: 18.132 + pixmap.fmt = IMG_FMT_RGBA32; 18.133 + break; 18.134 + case FMT_RGBA_FLOAT: 18.135 + pixmap.fmt = IMG_FMT_RGBAF; 18.136 + break; 18.137 + default: 18.138 + return false; 18.139 + } 18.140 + 18.141 + pixmap.width = width; 18.142 + pixmap.height = height; 18.143 + pixmap.pixels = pixels; 18.144 + pixmap.pixelsz = pixel_size(fmt); 18.145 + 18.146 + if(img_save(&pixmap, fname) == -1) { 18.147 + return false; 18.148 + } 18.149 + return true; 18.150 +} 18.151 + 18.152 +static int pixel_elements(Image::Format fmt) 18.153 +{ 18.154 + switch(fmt) { 18.155 + case Image::FMT_GREY: 18.156 + case Image::FMT_GREY_FLOAT: 18.157 + return 1; 18.158 + 18.159 + case Image::FMT_RGB: 18.160 + case Image::FMT_RGB_FLOAT: 18.161 + return 3; 18.162 + 18.163 + case Image::FMT_RGBA: 18.164 + case Image::FMT_RGBA_FLOAT: 18.165 + return 4; 18.166 + 18.167 + default: 18.168 + break; 18.169 + } 18.170 + return 0; 18.171 +} 18.172 + 18.173 +static int elem_size(Image::Format fmt) 18.174 +{ 18.175 + switch(fmt) { 18.176 + case Image::FMT_GREY: 18.177 + case Image::FMT_RGB: 18.178 + case Image::FMT_RGBA: 18.179 + return 1; 18.180 + 18.181 + case Image::FMT_GREY_FLOAT: 18.182 + case Image::FMT_RGB_FLOAT: 18.183 + case Image::FMT_RGBA_FLOAT: 18.184 + return sizeof(float); 18.185 + 18.186 + default: 18.187 + break; 18.188 + } 18.189 + return 0; 18.190 +} 18.191 + 18.192 +static int pixel_size(Image::Format fmt) 18.193 +{ 18.194 + return elem_size(fmt) * pixel_elements(fmt); 18.195 +}
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 19.2 +++ b/src/image.h Thu Nov 14 05:27:09 2013 +0200 19.3 @@ -0,0 +1,38 @@ 19.4 +#ifndef IMAGE_H_ 19.5 +#define IMAGE_H_ 19.6 + 19.7 + 19.8 +class Image { 19.9 +public: 19.10 + enum Format { 19.11 + FMT_GREY, 19.12 + FMT_RGB, 19.13 + FMT_RGBA, 19.14 + FMT_GREY_FLOAT, 19.15 + FMT_RGB_FLOAT, 19.16 + FMT_RGBA_FLOAT 19.17 + }; 19.18 + 19.19 +private: 19.20 + Format fmt; 19.21 + int width, height; 19.22 + void *pixels; 19.23 + 19.24 +public: 19.25 + Image(); 19.26 + ~Image(); 19.27 + 19.28 + int get_width() const; 19.29 + int get_height() const; 19.30 + 19.31 + Format get_format() const; 19.32 + 19.33 + bool create(int x, int y, Format fmt = FMT_RGBA); 19.34 + bool set_pixels(int x, int y, void *pixels, Format fmt = FMT_RGBA); 19.35 + void *get_pixels() const; 19.36 + 19.37 + bool load(const char *fname); 19.38 + bool save(const char *fname) const; 19.39 +}; 19.40 + 19.41 +#endif // IMAGE_H_
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 20.2 +++ b/src/logger.cc Thu Nov 14 05:27:09 2013 +0200 20.3 @@ -0,0 +1,96 @@ 20.4 +#include <stdio.h> 20.5 +#include <stdarg.h> 20.6 +#include "logger.h" 20.7 + 20.8 +#if defined(unix) || defined(__unix__) || defined(__APPLE__) 20.9 +#include <unistd.h> 20.10 +#endif 20.11 + 20.12 +enum { LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG }; 20.13 + 20.14 +static int typecolor(int type); 20.15 + 20.16 +static FILE *fp = stdout; 20.17 + 20.18 +static void logmsg(int type, const char *fmt, va_list ap) 20.19 +{ 20.20 +#if defined(unix) || defined(__unix__) || (defined(__APPLE__) && !defined(TARGET_IPHONE)) 20.21 + if(isatty(fileno(fp)) && type != LOG_INFO) { 20.22 + int c = typecolor(type); 20.23 + fprintf(fp, "\033[%dm", c); 20.24 + vfprintf(fp, fmt, ap); 20.25 + fprintf(fp, "\033[0m"); 20.26 + } else 20.27 +#endif 20.28 + { 20.29 + vfprintf(fp, fmt, ap); 20.30 + } 20.31 + if(type == LOG_ERROR || type == LOG_DEBUG) { 20.32 + fflush(fp); 20.33 + } 20.34 +} 20.35 + 20.36 +void info_log(const char *fmt, ...) 20.37 +{ 20.38 + va_list ap; 20.39 + 20.40 + va_start(ap, fmt); 20.41 + logmsg(LOG_INFO, fmt, ap); 20.42 + va_end(ap); 20.43 +} 20.44 + 20.45 +void warning_log(const char *fmt, ...) 20.46 +{ 20.47 + va_list ap; 20.48 + 20.49 + va_start(ap, fmt); 20.50 + logmsg(LOG_WARNING, fmt, ap); 20.51 + va_end(ap); 20.52 +} 20.53 + 20.54 +void error_log(const char *fmt, ...) 20.55 +{ 20.56 + va_list ap; 20.57 + 20.58 + va_start(ap, fmt); 20.59 + logmsg(LOG_ERROR, fmt, ap); 20.60 + va_end(ap); 20.61 +} 20.62 + 20.63 +void debug_log(const char *fmt, ...) 20.64 +{ 20.65 + va_list ap; 20.66 + 20.67 + va_start(ap, fmt); 20.68 + logmsg(LOG_DEBUG, fmt, ap); 20.69 + va_end(ap); 20.70 +} 20.71 + 20.72 +enum { 20.73 + BLACK = 0, 20.74 + RED, 20.75 + GREEN, 20.76 + YELLOW, 20.77 + BLUE, 20.78 + MAGENTA, 20.79 + CYAN, 20.80 + WHITE 20.81 +}; 20.82 + 20.83 +#define ANSI_FGCOLOR(x) (30 + (x)) 20.84 +#define ANSI_BGCOLOR(x) (40 + (x)) 20.85 + 20.86 +static int typecolor(int type) 20.87 +{ 20.88 + switch(type) { 20.89 + case LOG_ERROR: 20.90 + return ANSI_FGCOLOR(RED); 20.91 + case LOG_WARNING: 20.92 + return ANSI_FGCOLOR(YELLOW); 20.93 + case LOG_DEBUG: 20.94 + return ANSI_FGCOLOR(MAGENTA); 20.95 + default: 20.96 + break; 20.97 + } 20.98 + return 37; 20.99 +}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/src/logger.h Thu Nov 14 05:27:09 2013 +0200 21.3 @@ -0,0 +1,9 @@ 21.4 +#ifndef LOGGER_H_ 21.5 +#define LOGGER_H_ 21.6 + 21.7 +void info_log(const char *fmt, ...); 21.8 +void warning_log(const char *fmt, ...); 21.9 +void error_log(const char *fmt, ...); 21.10 +void debug_log(const char *fmt, ...); 21.11 + 21.12 +#endif // LOGGER_H_
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 22.2 +++ b/src/material.cc Thu Nov 14 05:27:09 2013 +0200 22.3 @@ -0,0 +1,65 @@ 22.4 +#include "material.h" 22.5 +#include "unistate.h" 22.6 + 22.7 +Material::Material() 22.8 + : diffuse(1, 1, 1), specular(0, 0, 0) 22.9 +{ 22.10 + alpha = 1.0; 22.11 + shininess = 1.0; 22.12 + 22.13 + for(int i=0; i<MAX_MTL_TEXTURES; i++) { 22.14 + tex[i] = 0; 22.15 + } 22.16 +} 22.17 + 22.18 + 22.19 +void Material::setup(bool use_textures) const 22.20 +{ 22.21 + static bool done_init; 22.22 + static int st_diffuse_idx, st_specular_idx, st_shininess_idx, st_alpha_idx; 22.23 + static int st_tex_diffuse_idx, st_tex_specular_idx, st_tex_normal_idx; 22.24 + static int st_tex_idx[MAX_MTL_TEXTURES]; 22.25 + 22.26 + if(!done_init) { 22.27 + st_diffuse_idx = add_unistate("st_mtl_diffuse", ST_FLOAT3); 22.28 + st_specular_idx = add_unistate("st_mtl_specular", ST_FLOAT3); 22.29 + st_shininess_idx = add_unistate("st_mtl_shininess", ST_FLOAT); 22.30 + st_alpha_idx = add_unistate("st_mtl_alpha", ST_FLOAT); 22.31 + st_tex_diffuse_idx = add_unistate("st_tex_diffuse", ST_INT); 22.32 + st_tex_specular_idx = add_unistate("st_tex_specular", ST_INT); 22.33 + st_tex_normal_idx = add_unistate("st_tex_normal", ST_INT); 22.34 + 22.35 + for(int i=0; i<MAX_MTL_TEXTURES; i++) { 22.36 + char name[32]; 22.37 + sprintf(name, "st_tex%d", i); 22.38 + st_tex_idx[i] = add_unistate(name, ST_INT); 22.39 + } 22.40 + done_init = true; 22.41 + } 22.42 + 22.43 + set_unistate(st_diffuse_idx, diffuse); 22.44 + set_unistate(st_specular_idx, specular); 22.45 + set_unistate(st_shininess_idx, shininess); 22.46 + set_unistate(st_alpha_idx, alpha); 22.47 + 22.48 + if(!use_textures) { 22.49 + return; // we're done 22.50 + } 22.51 + 22.52 + const int tex_named_idx[] = { 22.53 + st_tex_diffuse_idx, st_tex_specular_idx, st_tex_normal_idx, -1 22.54 + }; 22.55 + 22.56 + int tex_unit = 0; 22.57 + for(int i=0; i<MAX_MTL_TEXTURES; i++) { 22.58 + if(tex[i]) { 22.59 + tex[i]->bind(tex_unit); 22.60 + 22.61 + if(tex_named_idx[i]) { 22.62 + set_unistate(tex_named_idx[i], tex_unit); 22.63 + } 22.64 + set_unistate(st_tex_idx[i], tex_unit); 22.65 + tex_unit++; 22.66 + } 22.67 + } 22.68 +}
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 23.2 +++ b/src/material.h Thu Nov 14 05:27:09 2013 +0200 23.3 @@ -0,0 +1,29 @@ 23.4 +#ifndef MATERIAL_H_ 23.5 +#define MATERIAL_H_ 23.6 + 23.7 +#include "vmath/vmath.h" 23.8 +#include "texture.h" 23.9 + 23.10 +enum { 23.11 + TEX_DIFFUSE, 23.12 + TEX_SPECULAR, 23.13 + TEX_NORMAL, 23.14 + TEX_MISC, 23.15 + 23.16 + MAX_MTL_TEXTURES 23.17 +}; 23.18 + 23.19 +class Material { 23.20 +public: 23.21 + Vector3 diffuse, specular; 23.22 + float alpha; 23.23 + float shininess; 23.24 + 23.25 + Texture *tex[MAX_MTL_TEXTURES]; 23.26 + 23.27 + Material(); 23.28 + 23.29 + void setup(bool use_textures = true) const; 23.30 +}; 23.31 + 23.32 +#endif // MATERIAL_H_
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 24.2 +++ b/src/mesh.cc Thu Nov 14 05:27:09 2013 +0200 24.3 @@ -0,0 +1,971 @@ 24.4 +#include <stdio.h> 24.5 +#include <stdlib.h> 24.6 +#include <float.h> 24.7 +#include <assert.h> 24.8 +#include "opengl.h" 24.9 +#include "mesh.h" 24.10 +#include "xform_node.h" 24.11 +#include "logger.h" 24.12 + 24.13 +int Mesh::global_sdr_loc[NUM_MESH_ATTR] = { 0, 1, 2, 3, 4, 5 }; 24.14 +unsigned int Mesh::intersect_mode = ISECT_DEFAULT; 24.15 +float Mesh::vertex_sel_dist = 0.01; 24.16 +float Mesh::vis_vecsize = 1.0; 24.17 + 24.18 +Mesh::Mesh() 24.19 +{ 24.20 + clear(); 24.21 + 24.22 + glGenBuffers(NUM_MESH_ATTR + 1, buffer_objects); 24.23 + 24.24 + for(int i=0; i<NUM_MESH_ATTR; i++) { 24.25 + vattr[i].vbo = buffer_objects[i]; 24.26 + } 24.27 + ibo = buffer_objects[NUM_MESH_ATTR]; 24.28 + wire_ibo = 0; 24.29 +} 24.30 + 24.31 +Mesh::~Mesh() 24.32 +{ 24.33 + glDeleteBuffers(NUM_MESH_ATTR + 1, buffer_objects); 24.34 + 24.35 + if(wire_ibo) { 24.36 + glDeleteBuffers(1, &wire_ibo); 24.37 + } 24.38 +} 24.39 + 24.40 +void Mesh::set_name(const char *name) 24.41 +{ 24.42 + this->name = name; 24.43 +} 24.44 + 24.45 +const char *Mesh::get_name() const 24.46 +{ 24.47 + return name.c_str(); 24.48 +} 24.49 + 24.50 +bool Mesh::has_attrib(int attr) const 24.51 +{ 24.52 + if(attr < 0 || attr >= NUM_MESH_ATTR) { 24.53 + return false; 24.54 + } 24.55 + 24.56 + // if neither of these is valid, then nobody has set this attribute 24.57 + return vattr[attr].vbo_valid || vattr[attr].data_valid; 24.58 +} 24.59 + 24.60 +void Mesh::clear() 24.61 +{ 24.62 + bones.clear(); 24.63 + 24.64 + for(int i=0; i<NUM_MESH_ATTR; i++) { 24.65 + vattr[i].nelem = 0; 24.66 + vattr[i].vbo_valid = false; 24.67 + vattr[i].data_valid = false; 24.68 + //vattr[i].sdr_loc = -1; 24.69 + vattr[i].data.clear(); 24.70 + } 24.71 + ibo_valid = false; 24.72 + idata.clear(); 24.73 + 24.74 + wire_ibo_valid = false; 24.75 + 24.76 + nverts = nfaces = 0; 24.77 + 24.78 + bsph_valid = false; 24.79 + aabb_valid = false; 24.80 +} 24.81 + 24.82 +float *Mesh::set_attrib_data(int attrib, int nelem, unsigned int num, const float *data) 24.83 +{ 24.84 + if(attrib < 0 || attrib >= NUM_MESH_ATTR) { 24.85 + error_log("%s: invalid attrib: %d\n", __FUNCTION__, attrib); 24.86 + return 0; 24.87 + } 24.88 + 24.89 + if(nverts && num != nverts) { 24.90 + error_log("%s: attribute count missmatch (%d instead of %d)\n", __FUNCTION__, num, nverts); 24.91 + return 0; 24.92 + } 24.93 + nverts = num; 24.94 + 24.95 + vattr[attrib].data.clear(); 24.96 + vattr[attrib].nelem = nelem; 24.97 + vattr[attrib].data.resize(num * nelem); 24.98 + 24.99 + if(data) { 24.100 + memcpy(&vattr[attrib].data[0], data, num * nelem * sizeof *data); 24.101 + } 24.102 + 24.103 + vattr[attrib].data_valid = true; 24.104 + vattr[attrib].vbo_valid = false; 24.105 + return &vattr[attrib].data[0]; 24.106 +} 24.107 + 24.108 +float *Mesh::get_attrib_data(int attrib) 24.109 +{ 24.110 + if(attrib < 0 || attrib >= NUM_MESH_ATTR) { 24.111 + error_log("%s: invalid attrib: %d\n", __FUNCTION__, attrib); 24.112 + return 0; 24.113 + } 24.114 + 24.115 + vattr[attrib].vbo_valid = false; 24.116 + return (float*)((const Mesh*)this)->get_attrib_data(attrib); 24.117 +} 24.118 + 24.119 +const float *Mesh::get_attrib_data(int attrib) const 24.120 +{ 24.121 + if(attrib < 0 || attrib >= NUM_MESH_ATTR) { 24.122 + error_log("%s: invalid attrib: %d\n", __FUNCTION__, attrib); 24.123 + return 0; 24.124 + } 24.125 + 24.126 + if(!vattr[attrib].data_valid) { 24.127 +#if GL_ES_VERSION_2_0 24.128 + error_log("%s: can't read back attrib data on CrippledGL ES\n", __FUNCTION__); 24.129 + return 0; 24.130 +#else 24.131 + if(!vattr[attrib].vbo_valid) { 24.132 + error_log("%s: unavailable attrib: %d\n", __FUNCTION__, attrib); 24.133 + return 0; 24.134 + } 24.135 + 24.136 + // local data copy is unavailable, grab the data from the vbo 24.137 + Mesh *m = (Mesh*)this; 24.138 + m->vattr[attrib].data.resize(nverts * vattr[attrib].nelem); 24.139 + 24.140 + glBindBuffer(GL_ARRAY_BUFFER, vattr[attrib].vbo); 24.141 + void *data = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY); 24.142 + memcpy(&m->vattr[attrib].data[0], data, nverts * vattr[attrib].nelem * sizeof(float)); 24.143 + glUnmapBuffer(GL_ARRAY_BUFFER); 24.144 + 24.145 + vattr[attrib].data_valid = true; 24.146 +#endif 24.147 + } 24.148 + 24.149 + return &vattr[attrib].data[0]; 24.150 +} 24.151 + 24.152 +void Mesh::set_attrib(int attrib, int idx, const Vector4 &v) 24.153 +{ 24.154 + float *data = get_attrib_data(attrib); 24.155 + if(data) { 24.156 + data += idx * vattr[attrib].nelem; 24.157 + for(int i=0; i<vattr[attrib].nelem; i++) { 24.158 + data[i] = v[i]; 24.159 + } 24.160 + } 24.161 +} 24.162 + 24.163 +Vector4 Mesh::get_attrib(int attrib, int idx) const 24.164 +{ 24.165 + Vector4 v(0.0, 0.0, 0.0, 1.0); 24.166 + const float *data = get_attrib_data(attrib); 24.167 + if(data) { 24.168 + data += idx * vattr[attrib].nelem; 24.169 + for(int i=0; i<vattr[attrib].nelem; i++) { 24.170 + v[i] = data[i]; 24.171 + } 24.172 + } 24.173 + return v; 24.174 +} 24.175 + 24.176 +unsigned int *Mesh::set_index_data(int num, const unsigned int *indices) 24.177 +{ 24.178 + int nidx = nfaces * 3; 24.179 + if(nidx && num != nidx) { 24.180 + error_log("%s: index count missmatch (%d instead of %d)\n", __FUNCTION__, num, nidx); 24.181 + return 0; 24.182 + } 24.183 + nfaces = num / 3; 24.184 + 24.185 + idata.clear(); 24.186 + idata.resize(num); 24.187 + 24.188 + if(indices) { 24.189 + memcpy(&idata[0], indices, num * sizeof *indices); 24.190 + } 24.191 + 24.192 + idata_valid = true; 24.193 + ibo_valid = false; 24.194 + 24.195 + return &idata[0]; 24.196 +} 24.197 + 24.198 +unsigned int *Mesh::get_index_data() 24.199 +{ 24.200 + ibo_valid = false; 24.201 + return (unsigned int*)((const Mesh*)this)->get_index_data(); 24.202 +} 24.203 + 24.204 +const unsigned int *Mesh::get_index_data() const 24.205 +{ 24.206 + if(!idata_valid) { 24.207 +#if GL_ES_VERSION_2_0 24.208 + error_log("%s: can't read back index data in CrippledGL ES\n", __FUNCTION__); 24.209 + return 0; 24.210 +#else 24.211 + if(!ibo_valid) { 24.212 + error_log("%s: indices unavailable\n", __FUNCTION__); 24.213 + return 0; 24.214 + } 24.215 + 24.216 + // local data copy is unavailable, gram the data from the ibo 24.217 + Mesh *m = (Mesh*)this; 24.218 + int nidx = nfaces * 3; 24.219 + m->idata.resize(nidx); 24.220 + 24.221 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 24.222 + void *data = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY); 24.223 + memcpy(&m->idata[0], data, nidx * sizeof(unsigned int)); 24.224 + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); 24.225 + 24.226 + idata_valid = true; 24.227 +#endif 24.228 + } 24.229 + 24.230 + return &idata[0]; 24.231 +} 24.232 + 24.233 +void Mesh::append(const Mesh &mesh) 24.234 +{ 24.235 + unsigned int idxoffs = nverts; 24.236 + 24.237 + nverts += mesh.nverts; 24.238 + nfaces += mesh.nfaces; 24.239 + 24.240 + for(int i=0; i<NUM_MESH_ATTR; i++) { 24.241 + if(has_attrib(i) && mesh.has_attrib(i)) { 24.242 + // force validating the data arrays 24.243 + get_attrib_data(i); 24.244 + mesh.get_attrib_data(i); 24.245 + 24.246 + // append the mesh data 24.247 + vattr[i].data.insert(vattr[i].data.end(), mesh.vattr[i].data.begin(), mesh.vattr[i].data.end()); 24.248 + } 24.249 + } 24.250 + 24.251 + if(ibo_valid || idata_valid) { 24.252 + // make index arrays valid 24.253 + get_index_data(); 24.254 + mesh.get_index_data(); 24.255 + 24.256 + size_t orig_sz = idata.size(); 24.257 + 24.258 + idata.insert(idata.end(), mesh.idata.begin(), mesh.idata.end()); 24.259 + 24.260 + // fixup all the new indices 24.261 + for(size_t i=orig_sz; i<idata.size(); i++) { 24.262 + idata[i] += idxoffs; 24.263 + } 24.264 + } 24.265 + 24.266 + // fuck everything 24.267 + wire_ibo_valid = false; 24.268 + aabb_valid = false; 24.269 + bsph_valid = false; 24.270 +} 24.271 + 24.272 +// assemble a complete vertex by adding all the useful attributes 24.273 +void Mesh::vertex(float x, float y, float z) 24.274 +{ 24.275 + cur_val[MESH_ATTR_VERTEX] = Vector4(x, y, z, 1.0f); 24.276 + vattr[MESH_ATTR_VERTEX].data_valid = true; 24.277 + vattr[MESH_ATTR_VERTEX].nelem = 3; 24.278 + 24.279 + for(int i=0; i<NUM_MESH_ATTR; i++) { 24.280 + if(vattr[i].data_valid) { 24.281 + for(int j=0; j<vattr[MESH_ATTR_VERTEX].nelem; j++) { 24.282 + vattr[i].data.push_back(cur_val[i][j]); 24.283 + } 24.284 + } 24.285 + vattr[i].vbo_valid = false; 24.286 + } 24.287 + 24.288 + if(idata_valid) { 24.289 + idata.clear(); 24.290 + } 24.291 + ibo_valid = idata_valid = false; 24.292 +} 24.293 + 24.294 +void Mesh::normal(float nx, float ny, float nz) 24.295 +{ 24.296 + cur_val[MESH_ATTR_NORMAL] = Vector4(nx, ny, nz, 1.0f); 24.297 + vattr[MESH_ATTR_NORMAL].data_valid = true; 24.298 + vattr[MESH_ATTR_NORMAL].nelem = 3; 24.299 +} 24.300 + 24.301 +void Mesh::tangent(float tx, float ty, float tz) 24.302 +{ 24.303 + cur_val[MESH_ATTR_TANGENT] = Vector4(tx, ty, tz, 1.0f); 24.304 + vattr[MESH_ATTR_TANGENT].data_valid = true; 24.305 + vattr[MESH_ATTR_TANGENT].nelem = 3; 24.306 +} 24.307 + 24.308 +void Mesh::texcoord(float u, float v, float w) 24.309 +{ 24.310 + cur_val[MESH_ATTR_TEXCOORD] = Vector4(u, v, w, 1.0f); 24.311 + vattr[MESH_ATTR_TEXCOORD].data_valid = true; 24.312 + vattr[MESH_ATTR_TEXCOORD].nelem = 3; 24.313 +} 24.314 + 24.315 +void Mesh::boneweights(float w1, float w2, float w3, float w4) 24.316 +{ 24.317 + cur_val[MESH_ATTR_BONEWEIGHTS] = Vector4(w1, w2, w3, w4); 24.318 + vattr[MESH_ATTR_BONEWEIGHTS].data_valid = true; 24.319 + vattr[MESH_ATTR_BONEWEIGHTS].nelem = 4; 24.320 +} 24.321 + 24.322 +void Mesh::boneidx(int idx1, int idx2, int idx3, int idx4) 24.323 +{ 24.324 + cur_val[MESH_ATTR_BONEIDX] = Vector4(idx1, idx2, idx3, idx4); 24.325 + vattr[MESH_ATTR_BONEIDX].data_valid = true; 24.326 + vattr[MESH_ATTR_BONEIDX].nelem = 4; 24.327 +} 24.328 + 24.329 +/// static function 24.330 +void Mesh::set_attrib_location(int attr, int loc) 24.331 +{ 24.332 + if(attr < 0 || attr >= NUM_MESH_ATTR) { 24.333 + return; 24.334 + } 24.335 + Mesh::global_sdr_loc[attr] = loc; 24.336 +} 24.337 + 24.338 +/// static function 24.339 +int Mesh::get_attrib_location(int attr) 24.340 +{ 24.341 + if(attr < 0 || attr >= NUM_MESH_ATTR) { 24.342 + return -1; 24.343 + } 24.344 + return Mesh::global_sdr_loc[attr]; 24.345 +} 24.346 + 24.347 +/// static function 24.348 +void Mesh::clear_attrib_locations() 24.349 +{ 24.350 + for(int i=0; i<NUM_MESH_ATTR; i++) { 24.351 + Mesh::global_sdr_loc[i] = -1; 24.352 + } 24.353 +} 24.354 + 24.355 +/// static function 24.356 +void Mesh::set_vis_vecsize(float sz) 24.357 +{ 24.358 + Mesh::vis_vecsize = sz; 24.359 +} 24.360 + 24.361 +float Mesh::get_vis_vecsize() 24.362 +{ 24.363 + return Mesh::vis_vecsize; 24.364 +} 24.365 + 24.366 +void Mesh::apply_xform(const Matrix4x4 &xform) 24.367 +{ 24.368 + Matrix4x4 dir_xform = xform; 24.369 + dir_xform[0][3] = dir_xform[1][3] = dir_xform[2][3] = 0.0f; 24.370 + dir_xform[3][0] = dir_xform[3][1] = dir_xform[3][2] = 0.0f; 24.371 + dir_xform[3][3] = 1.0f; 24.372 + 24.373 + apply_xform(xform, dir_xform); 24.374 +} 24.375 + 24.376 +void Mesh::apply_xform(const Matrix4x4 &xform, const Matrix4x4 &dir_xform) 24.377 +{ 24.378 + for(unsigned int i=0; i<nverts; i++) { 24.379 + Vector4 v = get_attrib(MESH_ATTR_VERTEX, i); 24.380 + set_attrib(MESH_ATTR_VERTEX, i, v.transformed(xform)); 24.381 + 24.382 + if(has_attrib(MESH_ATTR_NORMAL)) { 24.383 + Vector3 n = get_attrib(MESH_ATTR_NORMAL, i); 24.384 + set_attrib(MESH_ATTR_NORMAL, i, n.transformed(dir_xform)); 24.385 + } 24.386 + if(has_attrib(MESH_ATTR_TANGENT)) { 24.387 + Vector3 t = get_attrib(MESH_ATTR_TANGENT, i); 24.388 + set_attrib(MESH_ATTR_TANGENT, i, t.transformed(dir_xform)); 24.389 + } 24.390 + } 24.391 +} 24.392 + 24.393 +int Mesh::add_bone(XFormNode *bone) 24.394 +{ 24.395 + int idx = bones.size(); 24.396 + bones.push_back(bone); 24.397 + return idx; 24.398 +} 24.399 + 24.400 +const XFormNode *Mesh::get_bone(int idx) const 24.401 +{ 24.402 + if(idx < 0 || idx >= (int)bones.size()) { 24.403 + return 0; 24.404 + } 24.405 + return bones[idx]; 24.406 +} 24.407 + 24.408 +int Mesh::get_bones_count() const 24.409 +{ 24.410 + return (int)bones.size(); 24.411 +} 24.412 + 24.413 +void Mesh::draw() const 24.414 +{ 24.415 + ((Mesh*)this)->update_buffers(); 24.416 + 24.417 + if(!vattr[MESH_ATTR_VERTEX].vbo_valid) { 24.418 + error_log("%s: invalid vertex buffer\n", __FUNCTION__); 24.419 + return; 24.420 + } 24.421 + if(global_sdr_loc[MESH_ATTR_VERTEX] == -1) { 24.422 + error_log("%s: shader attribute location for vertices unset\n", __FUNCTION__); 24.423 + return; 24.424 + } 24.425 + 24.426 + for(int i=0; i<NUM_MESH_ATTR; i++) { 24.427 + int loc = global_sdr_loc[i]; 24.428 + if(loc >= 0 && vattr[i].vbo_valid) { 24.429 + glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo); 24.430 + glVertexAttribPointer(loc, vattr[i].nelem, GL_FLOAT, GL_FALSE, 0, 0); 24.431 + glEnableVertexAttribArray(loc); 24.432 + } 24.433 + } 24.434 + glBindBuffer(GL_ARRAY_BUFFER, 0); 24.435 + 24.436 + if(ibo_valid) { 24.437 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 24.438 + glDrawElements(GL_TRIANGLES, nfaces * 3, GL_UNSIGNED_INT, 0); 24.439 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 24.440 + } else { 24.441 + glDrawArrays(GL_TRIANGLES, 0, nverts); 24.442 + } 24.443 + 24.444 + for(int i=0; i<NUM_MESH_ATTR; i++) { 24.445 + int loc = global_sdr_loc[i]; 24.446 + if(loc >= 0 && vattr[i].vbo_valid) { 24.447 + glDisableVertexAttribArray(loc); 24.448 + } 24.449 + } 24.450 +} 24.451 + 24.452 +void Mesh::draw_wire() const 24.453 +{ 24.454 + ((Mesh*)this)->update_wire_ibo(); 24.455 + 24.456 + if(!vattr[MESH_ATTR_VERTEX].vbo_valid || !wire_ibo_valid) { 24.457 + error_log("%s: invalid vertex buffer\n", __FUNCTION__); 24.458 + return; 24.459 + } 24.460 + if(global_sdr_loc[MESH_ATTR_VERTEX] == -1) { 24.461 + error_log("%s: shader attribute location for vertices unset\n", __FUNCTION__); 24.462 + return; 24.463 + } 24.464 + 24.465 + for(int i=0; i<NUM_MESH_ATTR; i++) { 24.466 + int loc = global_sdr_loc[i]; 24.467 + if(loc >= 0 && vattr[i].vbo_valid) { 24.468 + glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo); 24.469 + glVertexAttribPointer(loc, vattr[i].nelem, GL_FLOAT, GL_FALSE, 0, 0); 24.470 + glEnableVertexAttribArray(loc); 24.471 + } 24.472 + } 24.473 + glBindBuffer(GL_ARRAY_BUFFER, 0); 24.474 + 24.475 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, wire_ibo); 24.476 + glDrawElements(GL_LINES, nfaces * 6, GL_UNSIGNED_INT, 0); 24.477 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 24.478 + 24.479 + for(int i=0; i<NUM_MESH_ATTR; i++) { 24.480 + int loc = global_sdr_loc[i]; 24.481 + if(loc >= 0 && vattr[i].vbo_valid) { 24.482 + glDisableVertexAttribArray(loc); 24.483 + } 24.484 + } 24.485 +} 24.486 + 24.487 +void Mesh::draw_vertices() const 24.488 +{ 24.489 + ((Mesh*)this)->update_buffers(); 24.490 + 24.491 + if(!vattr[MESH_ATTR_VERTEX].vbo_valid) { 24.492 + error_log("%s: invalid vertex buffer\n", __FUNCTION__); 24.493 + return; 24.494 + } 24.495 + if(global_sdr_loc[MESH_ATTR_VERTEX] == -1) { 24.496 + error_log("%s: shader attribute location for vertices unset\n", __FUNCTION__); 24.497 + return; 24.498 + } 24.499 + 24.500 + for(int i=0; i<NUM_MESH_ATTR; i++) { 24.501 + int loc = global_sdr_loc[i]; 24.502 + if(loc >= 0 && vattr[i].vbo_valid) { 24.503 + glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo); 24.504 + glVertexAttribPointer(loc, vattr[i].nelem, GL_FLOAT, GL_FALSE, 0, 0); 24.505 + glEnableVertexAttribArray(loc); 24.506 + } 24.507 + } 24.508 + glBindBuffer(GL_ARRAY_BUFFER, 0); 24.509 + 24.510 + glDrawArrays(GL_POINTS, 0, nverts); 24.511 + 24.512 + for(int i=0; i<NUM_MESH_ATTR; i++) { 24.513 + int loc = global_sdr_loc[i]; 24.514 + if(loc >= 0 && vattr[i].vbo_valid) { 24.515 + glDisableVertexAttribArray(loc); 24.516 + } 24.517 + } 24.518 +} 24.519 + 24.520 +void Mesh::draw_normals() const 24.521 +{ 24.522 +#ifdef USE_OLDGL 24.523 + int vert_loc = global_sdr_loc[MESH_ATTR_VERTEX]; 24.524 + Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX); 24.525 + Vector3 *norm = (Vector3*)get_attrib_data(MESH_ATTR_NORMAL); 24.526 + 24.527 + if(!varr || !norm || vert_loc < 0) { 24.528 + return; 24.529 + } 24.530 + 24.531 + glBegin(GL_LINES); 24.532 + for(size_t i=0; i<nverts; i++) { 24.533 + glVertexAttrib3f(vert_loc, varr[i].x, varr[i].y, varr[i].z); 24.534 + Vector3 end = varr[i] + norm[i] * vis_vecsize; 24.535 + glVertexAttrib3f(vert_loc, end.x, end.y, end.z); 24.536 + } 24.537 + glEnd(); 24.538 + 24.539 +#endif // USE_OLDGL 24.540 +} 24.541 + 24.542 +void Mesh::draw_tangents() const 24.543 +{ 24.544 +#ifdef USE_OLDGL 24.545 + int vert_loc = global_sdr_loc[MESH_ATTR_VERTEX]; 24.546 + Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX); 24.547 + Vector3 *tang = (Vector3*)get_attrib_data(MESH_ATTR_TANGENT); 24.548 + 24.549 + if(!varr || !tang || vert_loc < 0) { 24.550 + return; 24.551 + } 24.552 + 24.553 + glBegin(GL_LINES); 24.554 + for(size_t i=0; i<nverts; i++) { 24.555 + glVertexAttrib3f(vert_loc, varr[i].x, varr[i].y, varr[i].z); 24.556 + Vector3 end = varr[i] + tang[i] * vis_vecsize; 24.557 + glVertexAttrib3f(vert_loc, end.x, end.y, end.z); 24.558 + } 24.559 + glEnd(); 24.560 + 24.561 +#endif // USE_OLDGL 24.562 +} 24.563 + 24.564 +void Mesh::get_aabbox(Vector3 *vmin, Vector3 *vmax) const 24.565 +{ 24.566 + if(!aabb_valid) { 24.567 + ((Mesh*)this)->calc_aabb(); 24.568 + } 24.569 + *vmin = aabb.min; 24.570 + *vmax = aabb.max; 24.571 +} 24.572 + 24.573 +const AABox &Mesh::get_aabbox() const 24.574 +{ 24.575 + if(!aabb_valid) { 24.576 + ((Mesh*)this)->calc_aabb(); 24.577 + } 24.578 + return aabb; 24.579 +} 24.580 + 24.581 +float Mesh::get_bsphere(Vector3 *center, float *rad) const 24.582 +{ 24.583 + if(!bsph_valid) { 24.584 + ((Mesh*)this)->calc_bsph(); 24.585 + } 24.586 + *center = bsph.center; 24.587 + *rad = bsph.radius; 24.588 + return bsph.radius; 24.589 +} 24.590 + 24.591 +const Sphere &Mesh::get_bsphere() const 24.592 +{ 24.593 + if(!bsph_valid) { 24.594 + ((Mesh*)this)->calc_bsph(); 24.595 + } 24.596 + return bsph; 24.597 +} 24.598 + 24.599 +/// static function 24.600 +void Mesh::set_intersect_mode(unsigned int mode) 24.601 +{ 24.602 + Mesh::intersect_mode = mode; 24.603 +} 24.604 + 24.605 +/// static function 24.606 +unsigned int Mesh::get_intersect_mode() 24.607 +{ 24.608 + return Mesh::intersect_mode; 24.609 +} 24.610 + 24.611 +/// static function 24.612 +void Mesh::set_vertex_select_distance(float dist) 24.613 +{ 24.614 + Mesh::vertex_sel_dist = dist; 24.615 +} 24.616 + 24.617 +/// static function 24.618 +float Mesh::get_vertex_select_distance() 24.619 +{ 24.620 + return Mesh::vertex_sel_dist; 24.621 +} 24.622 + 24.623 +bool Mesh::intersect(const Ray &ray, HitPoint *hit) const 24.624 +{ 24.625 + assert((Mesh::intersect_mode & (ISECT_VERTICES | ISECT_FACE)) != (ISECT_VERTICES | ISECT_FACE)); 24.626 + 24.627 + const Vector3 *varr = (Vector3*)get_attrib_data(MESH_ATTR_VERTEX); 24.628 + const Vector3 *narr = (Vector3*)get_attrib_data(MESH_ATTR_NORMAL); 24.629 + if(!varr) { 24.630 + return false; 24.631 + } 24.632 + const unsigned int *idxarr = get_index_data(); 24.633 + 24.634 + // first test with the bounding box 24.635 + AABox box; 24.636 + get_aabbox(&box.min, &box.max); 24.637 + if(!box.intersect(ray)) { 24.638 + return false; 24.639 + } 24.640 + 24.641 + HitPoint nearest_hit; 24.642 + nearest_hit.dist = FLT_MAX; 24.643 + nearest_hit.obj = 0; 24.644 + 24.645 + if(Mesh::intersect_mode & ISECT_VERTICES) { 24.646 + // we asked for "intersections" with the vertices of the mesh 24.647 + long nearest_vidx = -1; 24.648 + float thres_sq = Mesh::vertex_sel_dist * Mesh::vertex_sel_dist; 24.649 + 24.650 + for(unsigned int i=0; i<nverts; i++) { 24.651 + 24.652 + if((Mesh::intersect_mode & ISECT_FRONT) && dot_product(narr[i], ray.dir) > 0) { 24.653 + continue; 24.654 + } 24.655 + 24.656 + // project the vertex onto the ray line 24.657 + float t = dot_product(varr[i] - ray.origin, ray.dir); 24.658 + Vector3 vproj = ray.origin + ray.dir * t; 24.659 + 24.660 + float dist_sq = (vproj - varr[i]).length_sq(); 24.661 + if(dist_sq < thres_sq) { 24.662 + if(!hit) { 24.663 + return true; 24.664 + } 24.665 + if(t < nearest_hit.dist) { 24.666 + nearest_hit.dist = t; 24.667 + nearest_vidx = i; 24.668 + } 24.669 + } 24.670 + } 24.671 + 24.672 + if(nearest_vidx != -1) { 24.673 + hitvert = varr[nearest_vidx]; 24.674 + nearest_hit.obj = &hitvert; 24.675 + } 24.676 + 24.677 + } else { 24.678 + // regular intersection test with polygons 24.679 + 24.680 + for(unsigned int i=0; i<nfaces; i++) { 24.681 + Triangle face(i, varr, idxarr); 24.682 + 24.683 + // ignore back-facing polygons if the mode flags include ISECT_FRONT 24.684 + if((Mesh::intersect_mode & ISECT_FRONT) && dot_product(face.get_normal(), ray.dir) > 0) { 24.685 + continue; 24.686 + } 24.687 + 24.688 + HitPoint fhit; 24.689 + if(face.intersect(ray, hit ? &fhit : 0)) { 24.690 + if(!hit) { 24.691 + return true; 24.692 + } 24.693 + if(fhit.dist < nearest_hit.dist) { 24.694 + nearest_hit = fhit; 24.695 + hitface = face; 24.696 + } 24.697 + } 24.698 + } 24.699 + } 24.700 + 24.701 + if(nearest_hit.obj) { 24.702 + if(hit) { 24.703 + *hit = nearest_hit; 24.704 + 24.705 + // if we are interested in the mesh and not the faces set obj to this 24.706 + if(Mesh::intersect_mode & ISECT_FACE) { 24.707 + hit->obj = &hitface; 24.708 + } else if(Mesh::intersect_mode & ISECT_VERTICES) { 24.709 + hit->obj = &hitvert; 24.710 + } else { 24.711 + hit->obj = this; 24.712 + } 24.713 + } 24.714 + return true; 24.715 + } 24.716 + return false; 24.717 +} 24.718 + 24.719 + 24.720 +// ------ private member functions ------ 24.721 + 24.722 +void Mesh::calc_aabb() 24.723 +{ 24.724 + // the cast is to force calling the const version which doesn't invalidate 24.725 + if(!((const Mesh*)this)->get_attrib_data(MESH_ATTR_VERTEX)) { 24.726 + return; 24.727 + } 24.728 + 24.729 + aabb.min = Vector3(FLT_MAX, FLT_MAX, FLT_MAX); 24.730 + aabb.max = -aabb.min; 24.731 + 24.732 + for(unsigned int i=0; i<nverts; i++) { 24.733 + Vector4 v = get_attrib(MESH_ATTR_VERTEX, i); 24.734 + for(int j=0; j<3; j++) { 24.735 + if(v[j] < aabb.min[j]) { 24.736 + aabb.min[j] = v[j]; 24.737 + } 24.738 + if(v[j] > aabb.max[j]) { 24.739 + aabb.max[j] = v[j]; 24.740 + } 24.741 + } 24.742 + } 24.743 + aabb_valid = true; 24.744 +} 24.745 + 24.746 +void Mesh::calc_bsph() 24.747 +{ 24.748 + // the cast is to force calling the const version which doesn't invalidate 24.749 + if(!((const Mesh*)this)->get_attrib_data(MESH_ATTR_VERTEX)) { 24.750 + return; 24.751 + } 24.752 + 24.753 + Vector3 v; 24.754 + bsph.center = Vector3(0, 0, 0); 24.755 + 24.756 + // first find the center 24.757 + for(unsigned int i=0; i<nverts; i++) { 24.758 + v = get_attrib(MESH_ATTR_VERTEX, i); 24.759 + bsph.center += v; 24.760 + } 24.761 + bsph.center /= (float)nverts; 24.762 + 24.763 + bsph.radius = 0.0f; 24.764 + for(unsigned int i=0; i<nverts; i++) { 24.765 + v = get_attrib(MESH_ATTR_VERTEX, i); 24.766 + float dist_sq = (v - bsph.center).length_sq(); 24.767 + if(dist_sq > bsph.radius) { 24.768 + bsph.radius = dist_sq; 24.769 + } 24.770 + } 24.771 + bsph.radius = sqrt(bsph.radius); 24.772 + 24.773 + bsph_valid = true; 24.774 +} 24.775 + 24.776 +void Mesh::update_buffers() 24.777 +{ 24.778 + for(int i=0; i<NUM_MESH_ATTR; i++) { 24.779 + if(has_attrib(i) && !vattr[i].vbo_valid) { 24.780 + glBindBuffer(GL_ARRAY_BUFFER, vattr[i].vbo); 24.781 + glBufferData(GL_ARRAY_BUFFER, nverts * vattr[i].nelem * sizeof(float), &vattr[i].data[0], GL_STATIC_DRAW); 24.782 + vattr[i].vbo_valid = true; 24.783 + } 24.784 + } 24.785 + glBindBuffer(GL_ARRAY_BUFFER, 0); 24.786 + 24.787 + if(idata_valid && !ibo_valid) { 24.788 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 24.789 + glBufferData(GL_ELEMENT_ARRAY_BUFFER, nfaces * 3 * sizeof(unsigned int), &idata[0], GL_STATIC_DRAW); 24.790 + ibo_valid = true; 24.791 + } 24.792 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 24.793 +} 24.794 + 24.795 +void Mesh::update_wire_ibo() 24.796 +{ 24.797 + update_buffers(); 24.798 + 24.799 + if(wire_ibo_valid) { 24.800 + return; 24.801 + } 24.802 + 24.803 + if(!wire_ibo) { 24.804 + glGenBuffers(1, &wire_ibo); 24.805 + } 24.806 + 24.807 + unsigned int *wire_idxarr = new unsigned int[nfaces * 6]; 24.808 + unsigned int *dest = wire_idxarr; 24.809 + 24.810 + if(ibo_valid) { 24.811 + // we're dealing with an indexed mesh 24.812 + const unsigned int *idxarr = ((const Mesh*)this)->get_index_data(); 24.813 + 24.814 + for(unsigned int i=0; i<nfaces; i++) { 24.815 + *dest++ = idxarr[0]; 24.816 + *dest++ = idxarr[1]; 24.817 + *dest++ = idxarr[1]; 24.818 + *dest++ = idxarr[2]; 24.819 + *dest++ = idxarr[2]; 24.820 + *dest++ = idxarr[0]; 24.821 + idxarr += 3; 24.822 + } 24.823 + } else { 24.824 + // not an indexed mesh ... 24.825 + for(unsigned int i=0; i<nfaces; i++) { 24.826 + int vidx = i * 3; 24.827 + *dest++ = vidx; 24.828 + *dest++ = vidx + 1; 24.829 + *dest++ = vidx + 1; 24.830 + *dest++ = vidx + 2; 24.831 + *dest++ = vidx + 2; 24.832 + *dest++ = vidx; 24.833 + } 24.834 + } 24.835 + 24.836 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, wire_ibo); 24.837 + glBufferData(GL_ELEMENT_ARRAY_BUFFER, nfaces * 6 * sizeof(unsigned int), wire_idxarr, GL_STATIC_DRAW); 24.838 + delete [] wire_idxarr; 24.839 + wire_ibo_valid = true; 24.840 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 24.841 +} 24.842 + 24.843 + 24.844 +// ------ class Triangle ------ 24.845 +Triangle::Triangle() 24.846 +{ 24.847 + normal_valid = false; 24.848 + id = -1; 24.849 +} 24.850 + 24.851 +Triangle::Triangle(const Vector3 &v0, const Vector3 &v1, const Vector3 &v2) 24.852 +{ 24.853 + v[0] = v0; 24.854 + v[1] = v1; 24.855 + v[2] = v2; 24.856 + normal_valid = false; 24.857 + id = -1; 24.858 +} 24.859 + 24.860 +Triangle::Triangle(int n, const Vector3 *varr, const unsigned int *idxarr) 24.861 +{ 24.862 + if(idxarr) { 24.863 + v[0] = varr[idxarr[n * 3]]; 24.864 + v[1] = varr[idxarr[n * 3 + 1]]; 24.865 + v[2] = varr[idxarr[n * 3 + 2]]; 24.866 + } else { 24.867 + v[0] = varr[n * 3]; 24.868 + v[1] = varr[n * 3 + 1]; 24.869 + v[2] = varr[n * 3 + 2]; 24.870 + } 24.871 + normal_valid = false; 24.872 + id = n; 24.873 +} 24.874 + 24.875 +void Triangle::calc_normal() 24.876 +{ 24.877 + normal = cross_product(v[1] - v[0], v[2] - v[0]).normalized(); 24.878 + normal_valid = true; 24.879 +} 24.880 + 24.881 +const Vector3 &Triangle::get_normal() const 24.882 +{ 24.883 + if(!normal_valid) { 24.884 + ((Triangle*)this)->calc_normal(); 24.885 + } 24.886 + return normal; 24.887 +} 24.888 + 24.889 +void Triangle::transform(const Matrix4x4 &xform) 24.890 +{ 24.891 + v[0].transform(xform); 24.892 + v[1].transform(xform); 24.893 + v[2].transform(xform); 24.894 + normal_valid = false; 24.895 +} 24.896 + 24.897 +void Triangle::draw() const 24.898 +{ 24.899 + Vector3 n[3]; 24.900 + n[0] = get_normal(); 24.901 + n[1] = get_normal(); 24.902 + n[2] = get_normal(); 24.903 + 24.904 + int vloc = Mesh::get_attrib_location(MESH_ATTR_VERTEX); 24.905 + int nloc = Mesh::get_attrib_location(MESH_ATTR_NORMAL); 24.906 + 24.907 + glEnableVertexAttribArray(vloc); 24.908 + glVertexAttribPointer(vloc, 3, GL_FLOAT, GL_FALSE, 0, &v[0].x); 24.909 + glVertexAttribPointer(nloc, 3, GL_FLOAT, GL_FALSE, 0, &n[0].x); 24.910 + 24.911 + glDrawArrays(GL_TRIANGLES, 0, 3); 24.912 + 24.913 + glDisableVertexAttribArray(vloc); 24.914 + glDisableVertexAttribArray(nloc); 24.915 + CHECKGLERR; 24.916 +} 24.917 + 24.918 +void Triangle::draw_wire() const 24.919 +{ 24.920 + static const int idxarr[] = {0, 1, 1, 2, 2, 0}; 24.921 + int vloc = Mesh::get_attrib_location(MESH_ATTR_VERTEX); 24.922 + 24.923 + glEnableVertexAttribArray(vloc); 24.924 + glVertexAttribPointer(vloc, 3, GL_FLOAT, GL_FALSE, 0, &v[0].x); 24.925 + 24.926 + glDrawElements(GL_LINES, 6, GL_UNSIGNED_INT, idxarr); 24.927 + 24.928 + glDisableVertexAttribArray(vloc); 24.929 + CHECKGLERR; 24.930 +} 24.931 + 24.932 +Vector3 Triangle::calc_barycentric(const Vector3 &pos) const 24.933 +{ 24.934 + Vector3 norm = get_normal(); 24.935 + 24.936 + float area_sq = fabs(dot_product(cross_product(v[1] - v[0], v[2] - v[0]), norm)); 24.937 + if(area_sq < 1e-5) { 24.938 + return Vector3(0, 0, 0); 24.939 + } 24.940 + 24.941 + float asq0 = fabs(dot_product(cross_product(v[1] - pos, v[2] - pos), norm)); 24.942 + float asq1 = fabs(dot_product(cross_product(v[2] - pos, v[0] - pos), norm)); 24.943 + float asq2 = fabs(dot_product(cross_product(v[0] - pos, v[1] - pos), norm)); 24.944 + 24.945 + return Vector3(asq0 / area_sq, asq1 / area_sq, asq2 / area_sq); 24.946 +} 24.947 + 24.948 +bool Triangle::intersect(const Ray &ray, HitPoint *hit) const 24.949 +{ 24.950 + Vector3 normal = get_normal(); 24.951 + 24.952 + float ndotdir = dot_product(ray.dir, normal); 24.953 + if(fabs(ndotdir) < 1e-4) { 24.954 + return false; 24.955 + } 24.956 + 24.957 + Vector3 vertdir = v[0] - ray.origin; 24.958 + float t = dot_product(normal, vertdir) / ndotdir; 24.959 + 24.960 + Vector3 pos = ray.origin + ray.dir * t; 24.961 + Vector3 bary = calc_barycentric(pos); 24.962 + 24.963 + if(bary.x + bary.y + bary.z > 1.00001) { 24.964 + return false; 24.965 + } 24.966 + 24.967 + if(hit) { 24.968 + hit->dist = t; 24.969 + hit->pos = ray.origin + ray.dir * t; 24.970 + hit->normal = normal; 24.971 + hit->obj = this; 24.972 + } 24.973 + return true; 24.974 +}
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 25.2 +++ b/src/mesh.h Thu Nov 14 05:27:09 2013 +0200 25.3 @@ -0,0 +1,211 @@ 25.4 +#ifndef MESH_H_ 25.5 +#define MESH_H_ 25.6 + 25.7 +#include <string> 25.8 +#include <vector> 25.9 +#include <vmath/vmath.h> 25.10 +#include "geom.h" 25.11 + 25.12 +enum { 25.13 + MESH_ATTR_VERTEX, 25.14 + MESH_ATTR_NORMAL, 25.15 + MESH_ATTR_TANGENT, 25.16 + MESH_ATTR_TEXCOORD, 25.17 + MESH_ATTR_COLOR, 25.18 + MESH_ATTR_BONEWEIGHTS, 25.19 + MESH_ATTR_BONEIDX, 25.20 + 25.21 + NUM_MESH_ATTR 25.22 +}; 25.23 + 25.24 +// intersection mode flags 25.25 +enum { 25.26 + ISECT_DEFAULT = 0, // default (whole mesh, all intersections) 25.27 + ISECT_FRONT = 1, // front-faces only 25.28 + ISECT_FACE = 2, // return intersected face pointer instead of mesh 25.29 + ISECT_VERTICES = 4 // return (?) TODO 25.30 +}; 25.31 + 25.32 +class XFormNode; 25.33 + 25.34 + 25.35 +class Triangle { 25.36 +public: 25.37 + Vector3 v[3]; 25.38 + Vector3 normal; 25.39 + bool normal_valid; 25.40 + int id; 25.41 + 25.42 + Triangle(); 25.43 + Triangle(const Vector3 &v0, const Vector3 &v1, const Vector3 &v2); 25.44 + Triangle(int n, const Vector3 *varr, const unsigned int *idxarr = 0); 25.45 + 25.46 + /// calculate normal (quite expensive) 25.47 + void calc_normal(); 25.48 + const Vector3 &get_normal() const; 25.49 + 25.50 + void transform(const Matrix4x4 &xform); 25.51 + 25.52 + void draw() const; 25.53 + void draw_wire() const; 25.54 + 25.55 + /// calculate barycentric coordinates of a point 25.56 + Vector3 calc_barycentric(const Vector3 &pos) const; 25.57 + 25.58 + bool intersect(const Ray &ray, HitPoint *hit = 0) const; 25.59 +}; 25.60 + 25.61 + 25.62 +class Mesh { 25.63 +private: 25.64 + std::string name; 25.65 + unsigned int nverts, nfaces; 25.66 + 25.67 + // current value for each attribute for the immedate mode 25.68 + // interface. 25.69 + Vector4 cur_val[NUM_MESH_ATTR]; 25.70 + 25.71 + unsigned int buffer_objects[NUM_MESH_ATTR + 1]; 25.72 + 25.73 + // vertex attribute data and buffer objects 25.74 + struct { 25.75 + int nelem; // number of elements per attribute range: [1, 4] 25.76 + std::vector<float> data; 25.77 + unsigned int vbo; 25.78 + mutable bool vbo_valid; // if this is false, the vbo needs updating from the data 25.79 + mutable bool data_valid; // if this is false, the data needs to be pulled from the vbo 25.80 + //int sdr_loc; 25.81 + } vattr[NUM_MESH_ATTR]; 25.82 + 25.83 + static int global_sdr_loc[NUM_MESH_ATTR]; 25.84 + 25.85 + std::vector<XFormNode*> bones; // bones affecting this mesh 25.86 + 25.87 + // index data and buffer object 25.88 + std::vector<unsigned int> idata; 25.89 + unsigned int ibo; 25.90 + mutable bool ibo_valid; 25.91 + mutable bool idata_valid; 25.92 + 25.93 + // index buffer object for wireframe rendering (constructed on demand) 25.94 + unsigned int wire_ibo; 25.95 + mutable bool wire_ibo_valid; 25.96 + 25.97 + // axis-aligned bounding box 25.98 + mutable AABox aabb; 25.99 + mutable bool aabb_valid; 25.100 + 25.101 + // bounding sphere 25.102 + mutable Sphere bsph; 25.103 + mutable bool bsph_valid; 25.104 + 25.105 + // keeps the last intersected face 25.106 + mutable Triangle hitface; 25.107 + // keeps the last intersected vertex position 25.108 + mutable Vector3 hitvert; 25.109 + 25.110 + void calc_aabb(); 25.111 + void calc_bsph(); 25.112 + 25.113 + static unsigned int intersect_mode; 25.114 + static float vertex_sel_dist; 25.115 + 25.116 + static float vis_vecsize; 25.117 + 25.118 + /// update the VBOs after data has changed (invalid vbo/ibo) 25.119 + void update_buffers(); 25.120 + /// construct/update the wireframe index buffer (called from draw_wire). 25.121 + void update_wire_ibo(); 25.122 + 25.123 + 25.124 +public: 25.125 + Mesh(); 25.126 + ~Mesh(); 25.127 + 25.128 + void set_name(const char *name); 25.129 + const char *get_name() const; 25.130 + 25.131 + bool has_attrib(int attr) const; 25.132 + 25.133 + // clears everything about this mesh, and returns to the newly constructed state 25.134 + void clear(); 25.135 + 25.136 + // access the vertex attribute data 25.137 + // if vdata == 0, space is just allocated 25.138 + float *set_attrib_data(int attrib, int nelem, unsigned int num, const float *vdata = 0); // invalidates vbo 25.139 + float *get_attrib_data(int attrib); // invalidates vbo 25.140 + const float *get_attrib_data(int attrib) const; 25.141 + 25.142 + // simple access to any particular attribute 25.143 + void set_attrib(int attrib, int idx, const Vector4 &v); // invalidates vbo 25.144 + Vector4 get_attrib(int attrib, int idx) const; 25.145 + 25.146 + // ... same for index data 25.147 + unsigned int *set_index_data(int num, const unsigned int *indices = 0); // invalidates ibo 25.148 + unsigned int *get_index_data(); // invalidates ibo 25.149 + const unsigned int *get_index_data() const; 25.150 + 25.151 + void append(const Mesh &mesh); 25.152 + 25.153 + // immediate-mode style mesh construction interface 25.154 + void vertex(float x, float y, float z); 25.155 + void normal(float nx, float ny, float nz); 25.156 + void tangent(float tx, float ty, float tz); 25.157 + void texcoord(float u, float v, float w); 25.158 + void boneweights(float w1, float w2, float w3, float w4); 25.159 + void boneidx(int idx1, int idx2, int idx3, int idx4); 25.160 + 25.161 + /* apply a transformation to the vertices and its inverse-transpose 25.162 + * to the normals and tangents. 25.163 + */ 25.164 + void apply_xform(const Matrix4x4 &xform); 25.165 + void apply_xform(const Matrix4x4 &xform, const Matrix4x4 &dir_xform); 25.166 + 25.167 + // adds a bone and returns its index 25.168 + int add_bone(XFormNode *bone); 25.169 + const XFormNode *get_bone(int idx) const; 25.170 + int get_bones_count() const; 25.171 + 25.172 + // access the shader attribute locations 25.173 + static void set_attrib_location(int attr, int loc); 25.174 + static int get_attrib_location(int attr); 25.175 + static void clear_attrib_locations(); 25.176 + 25.177 + static void set_vis_vecsize(float sz); 25.178 + static float get_vis_vecsize(); 25.179 + 25.180 + void draw() const; 25.181 + void draw_wire() const; 25.182 + void draw_vertices() const; 25.183 + void draw_normals() const; 25.184 + void draw_tangents() const; 25.185 + 25.186 + /** get the bounding box in local space. The result will be cached, and subsequent 25.187 + * calls will return the same box. The cache gets invalidated by any functions that can affect 25.188 + * the vertex data (non-const variant of get_attrib_data(MESH_ATTR_VERTEX, ...) included). 25.189 + * @{ */ 25.190 + void get_aabbox(Vector3 *vmin, Vector3 *vmax) const; 25.191 + const AABox &get_aabbox() const; 25.192 + /// @} 25.193 + 25.194 + /** get the bounding sphere in local space. The result will be cached, and subsequent 25.195 + * calls will return the same box. The cache gets invalidated by any functions that can affect 25.196 + * the vertex data (non-const variant of get_attrib_data(MESH_ATTR_VERTEX, ...) included). 25.197 + * @{ */ 25.198 + float get_bsphere(Vector3 *center, float *rad) const; 25.199 + const Sphere &get_bsphere() const; 25.200 + 25.201 + static void set_intersect_mode(unsigned int mode); 25.202 + static unsigned int get_intersect_mode(); 25.203 + static void set_vertex_select_distance(float dist); 25.204 + static float get_vertex_select_distance(); 25.205 + 25.206 + /** Find the intersection between the mesh and a ray. 25.207 + * XXX Brute force at the moment, not intended to be used for anything other than picking in tools. 25.208 + * If you intend to use it in a speed-critical part of the code, you'll *have* to optimize it! 25.209 + */ 25.210 + bool intersect(const Ray &ray, HitPoint *hit = 0) const; 25.211 +}; 25.212 + 25.213 + 25.214 +#endif // MESH_H_
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/src/meshgen.cc Thu Nov 14 05:27:09 2013 +0200 26.3 @@ -0,0 +1,373 @@ 26.4 +#include "meshgen.h" 26.5 +#include "mesh.h" 26.6 +#include "logger.h" 26.7 + 26.8 +// -------- sphere -------- 26.9 + 26.10 +#define SURAD(u) ((u) * 2.0 * M_PI) 26.11 +#define SVRAD(v) ((v) * M_PI) 26.12 + 26.13 +static Vector3 sphvec(float theta, float phi) 26.14 +{ 26.15 + return Vector3(sin(theta) * sin(phi), 26.16 + cos(phi), 26.17 + cos(theta) * sin(phi)); 26.18 +} 26.19 + 26.20 +void gen_sphere(Mesh *mesh, float rad, int usub, int vsub, float urange, float vrange) 26.21 +{ 26.22 + if(usub < 4) usub = 4; 26.23 + if(vsub < 2) vsub = 2; 26.24 + 26.25 + int uverts = usub + 1; 26.26 + int vverts = vsub + 1; 26.27 + 26.28 + int num_verts = uverts * vverts; 26.29 + int num_quads = usub * vsub; 26.30 + int num_tri = num_quads * 2; 26.31 + 26.32 + mesh->clear(); 26.33 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 26.34 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 26.35 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 26.36 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 26.37 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 26.38 + 26.39 + float du = urange / (float)(uverts - 1); 26.40 + float dv = vrange / (float)(vverts - 1); 26.41 + 26.42 + float u = 0.0; 26.43 + for(int i=0; i<uverts; i++) { 26.44 + float theta = SURAD(u * urange); 26.45 + 26.46 + float v = 0.0; 26.47 + for(int j=0; j<vverts; j++) { 26.48 + float phi = SVRAD(v * vrange); 26.49 + 26.50 + Vector3 pos = sphvec(theta, phi); 26.51 + 26.52 + *varr++ = pos * rad; 26.53 + *narr++ = pos; 26.54 + *tarr++ = (sphvec(theta + 0.1, M_PI / 2.0) - sphvec(theta - 0.1, M_PI / 2.0)).normalized(); 26.55 + *uvarr++ = Vector2(u * urange, v * vrange); 26.56 + 26.57 + if(i < usub && j < vsub) { 26.58 + int idx = i * vverts + j; 26.59 + *idxarr++ = idx; 26.60 + *idxarr++ = idx + 1; 26.61 + *idxarr++ = idx + vverts + 1; 26.62 + 26.63 + *idxarr++ = idx; 26.64 + *idxarr++ = idx + vverts + 1; 26.65 + *idxarr++ = idx + vverts; 26.66 + } 26.67 + 26.68 + v += dv; 26.69 + } 26.70 + u += du; 26.71 + } 26.72 +} 26.73 + 26.74 + 26.75 +// -------- cylinder -------- 26.76 + 26.77 +static Vector3 cylvec(float theta, float height) 26.78 +{ 26.79 + return Vector3(sin(theta), height, cos(theta)); 26.80 +} 26.81 + 26.82 +void gen_cylinder(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange) 26.83 +{ 26.84 + if(usub < 4) usub = 4; 26.85 + if(vsub < 1) vsub = 1; 26.86 + 26.87 + int uverts = usub + 1; 26.88 + int vverts = vsub + 1; 26.89 + 26.90 + int num_body_verts = uverts * vverts; 26.91 + int num_body_quads = usub * vsub; 26.92 + int num_body_tri = num_body_quads * 2; 26.93 + 26.94 + int capvverts = capsub ? capsub + 1 : 0; 26.95 + int num_cap_verts = uverts * capvverts; 26.96 + int num_cap_quads = usub * capsub; 26.97 + int num_cap_tri = num_cap_quads * 2; 26.98 + 26.99 + int num_verts = num_body_verts + num_cap_verts * 2; 26.100 + int num_tri = num_body_tri + num_cap_tri * 2; 26.101 + 26.102 + mesh->clear(); 26.103 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 26.104 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 26.105 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 26.106 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 26.107 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 26.108 + 26.109 + float du = urange / (float)(uverts - 1); 26.110 + float dv = vrange / (float)(vverts - 1); 26.111 + 26.112 + float u = 0.0; 26.113 + for(int i=0; i<uverts; i++) { 26.114 + float theta = SURAD(u); 26.115 + 26.116 + float v = 0.0; 26.117 + for(int j=0; j<vverts; j++) { 26.118 + float y = (v - 0.5) * height; 26.119 + Vector3 pos = cylvec(theta, y); 26.120 + 26.121 + *varr++ = Vector3(pos.x * rad, pos.y, pos.z * rad); 26.122 + *narr++ = Vector3(pos.x, 0.0, pos.z); 26.123 + *tarr++ = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized(); 26.124 + *uvarr++ = Vector2(u * urange, v * vrange); 26.125 + 26.126 + if(i < usub && j < vsub) { 26.127 + int idx = i * vverts + j; 26.128 + 26.129 + *idxarr++ = idx; 26.130 + *idxarr++ = idx + vverts + 1; 26.131 + *idxarr++ = idx + 1; 26.132 + 26.133 + *idxarr++ = idx; 26.134 + *idxarr++ = idx + vverts; 26.135 + *idxarr++ = idx + vverts + 1; 26.136 + } 26.137 + 26.138 + v += dv; 26.139 + } 26.140 + u += du; 26.141 + } 26.142 + 26.143 + 26.144 + // now the cap! 26.145 + if(!capsub) { 26.146 + return; 26.147 + } 26.148 + 26.149 + dv = 1.0 / (float)(capvverts - 1); 26.150 + 26.151 + u = 0.0; 26.152 + for(int i=0; i<uverts; i++) { 26.153 + float theta = SURAD(u); 26.154 + 26.155 + float v = 0.0; 26.156 + for(int j=0; j<capvverts; j++) { 26.157 + float r = v * rad; 26.158 + 26.159 + Vector3 pos = cylvec(theta, height / 2.0) * r; 26.160 + pos.y = height / 2.0; 26.161 + Vector3 tang = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized(); 26.162 + 26.163 + *varr++ = pos; 26.164 + *narr++ = Vector3(0, 1, 0); 26.165 + *tarr++ = tang; 26.166 + *uvarr++ = Vector2(u * urange, v); 26.167 + 26.168 + pos.y = -height / 2.0; 26.169 + *varr++ = pos; 26.170 + *narr++ = Vector3(0, -1, 0); 26.171 + *tarr++ = -tang; 26.172 + *uvarr++ = Vector2(u * urange, v); 26.173 + 26.174 + if(i < usub && j < capsub) { 26.175 + unsigned int idx = num_body_verts + (i * capvverts + j) * 2; 26.176 + 26.177 + unsigned int vidx[4] = { 26.178 + idx, 26.179 + idx + capvverts * 2, 26.180 + idx + (capvverts + 1) * 2, 26.181 + idx + 2 26.182 + }; 26.183 + 26.184 + *idxarr++ = vidx[0]; 26.185 + *idxarr++ = vidx[2]; 26.186 + *idxarr++ = vidx[1]; 26.187 + *idxarr++ = vidx[0]; 26.188 + *idxarr++ = vidx[3]; 26.189 + *idxarr++ = vidx[2]; 26.190 + 26.191 + *idxarr++ = vidx[0] + 1; 26.192 + *idxarr++ = vidx[1] + 1; 26.193 + *idxarr++ = vidx[2] + 1; 26.194 + *idxarr++ = vidx[0] + 1; 26.195 + *idxarr++ = vidx[2] + 1; 26.196 + *idxarr++ = vidx[3] + 1; 26.197 + } 26.198 + 26.199 + v += dv; 26.200 + } 26.201 + u += du; 26.202 + } 26.203 +} 26.204 + 26.205 +// -------- cone -------- 26.206 + 26.207 +static Vector3 conevec(float theta, float y, float height) 26.208 +{ 26.209 + float scale = 1.0 - y / height; 26.210 + return Vector3(sin(theta) * scale, y, cos(theta) * scale); 26.211 +} 26.212 + 26.213 +void gen_cone(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange) 26.214 +{ 26.215 + if(usub < 4) usub = 4; 26.216 + if(vsub < 1) vsub = 1; 26.217 + 26.218 + int uverts = usub + 1; 26.219 + int vverts = vsub + 1; 26.220 + 26.221 + int num_body_verts = uverts * vverts; 26.222 + int num_body_quads = usub * vsub; 26.223 + int num_body_tri = num_body_quads * 2; 26.224 + 26.225 + int capvverts = capsub ? capsub + 1 : 0; 26.226 + int num_cap_verts = uverts * capvverts; 26.227 + int num_cap_quads = usub * capsub; 26.228 + int num_cap_tri = num_cap_quads * 2; 26.229 + 26.230 + int num_verts = num_body_verts + num_cap_verts; 26.231 + int num_tri = num_body_tri + num_cap_tri; 26.232 + 26.233 + mesh->clear(); 26.234 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 26.235 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 26.236 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 26.237 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 26.238 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 26.239 + 26.240 + float du = urange / (float)(uverts - 1); 26.241 + float dv = vrange / (float)(vverts - 1); 26.242 + 26.243 + float u = 0.0; 26.244 + for(int i=0; i<uverts; i++) { 26.245 + float theta = SURAD(u); 26.246 + 26.247 + float v = 0.0; 26.248 + for(int j=0; j<vverts; j++) { 26.249 + float y = v * height; 26.250 + Vector3 pos = conevec(theta, y, height); 26.251 + 26.252 + Vector3 tang = (conevec(theta + 0.1, 0.0, height) - conevec(theta - 0.1, 0.0, height)).normalized(); 26.253 + Vector3 bitang = (conevec(theta, y + 0.1, height) - pos).normalized(); 26.254 + 26.255 + *varr++ = Vector3(pos.x * rad, pos.y, pos.z * rad); 26.256 + *narr++ = cross_product(tang, bitang); 26.257 + *tarr++ = tang; 26.258 + *uvarr++ = Vector2(u * urange, v * vrange); 26.259 + 26.260 + if(i < usub && j < vsub) { 26.261 + int idx = i * vverts + j; 26.262 + 26.263 + *idxarr++ = idx; 26.264 + *idxarr++ = idx + vverts + 1; 26.265 + *idxarr++ = idx + 1; 26.266 + 26.267 + *idxarr++ = idx; 26.268 + *idxarr++ = idx + vverts; 26.269 + *idxarr++ = idx + vverts + 1; 26.270 + } 26.271 + 26.272 + v += dv; 26.273 + } 26.274 + u += du; 26.275 + } 26.276 + 26.277 + 26.278 + // now the bottom cap! 26.279 + if(!capsub) { 26.280 + return; 26.281 + } 26.282 + 26.283 + dv = 1.0 / (float)(capvverts - 1); 26.284 + 26.285 + u = 0.0; 26.286 + for(int i=0; i<uverts; i++) { 26.287 + float theta = SURAD(u); 26.288 + 26.289 + float v = 0.0; 26.290 + for(int j=0; j<capvverts; j++) { 26.291 + float r = v * rad; 26.292 + 26.293 + Vector3 pos = conevec(theta, 0.0, height) * r; 26.294 + Vector3 tang = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized(); 26.295 + 26.296 + *varr++ = pos; 26.297 + *narr++ = Vector3(0, -1, 0); 26.298 + *tarr++ = tang; 26.299 + *uvarr++ = Vector2(u * urange, v); 26.300 + 26.301 + if(i < usub && j < capsub) { 26.302 + unsigned int idx = num_body_verts + i * capvverts + j; 26.303 + 26.304 + unsigned int vidx[4] = { 26.305 + idx, 26.306 + idx + capvverts, 26.307 + idx + (capvverts + 1), 26.308 + idx + 1 26.309 + }; 26.310 + 26.311 + *idxarr++ = vidx[0]; 26.312 + *idxarr++ = vidx[1]; 26.313 + *idxarr++ = vidx[2]; 26.314 + *idxarr++ = vidx[0]; 26.315 + *idxarr++ = vidx[2]; 26.316 + *idxarr++ = vidx[3]; 26.317 + } 26.318 + 26.319 + v += dv; 26.320 + } 26.321 + u += du; 26.322 + } 26.323 +} 26.324 + 26.325 + 26.326 +// -------- plane -------- 26.327 + 26.328 +void gen_plane(Mesh *mesh, float width, float height, int usub, int vsub) 26.329 +{ 26.330 + if(usub < 1) usub = 1; 26.331 + if(vsub < 1) vsub = 1; 26.332 + 26.333 + mesh->clear(); 26.334 + 26.335 + int uverts = usub + 1; 26.336 + int vverts = vsub + 1; 26.337 + int num_verts = uverts * vverts; 26.338 + 26.339 + int num_quads = usub * vsub; 26.340 + int num_tri = num_quads * 2; 26.341 + 26.342 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 26.343 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 26.344 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 26.345 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 26.346 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 26.347 + 26.348 + float du = 1.0 / (float)usub; 26.349 + float dv = 1.0 / (float)vsub; 26.350 + 26.351 + float u = 0.0; 26.352 + for(int i=0; i<uverts; i++) { 26.353 + float v = 0.0; 26.354 + for(int j=0; j<vverts; j++) { 26.355 + *varr++ = Vector3((u - 0.5) * width, (v - 0.5) * height, 0.0); 26.356 + *narr++ = Vector3(0, 0, 1); 26.357 + *tarr++ = Vector3(1, 0, 0); 26.358 + *uvarr++ = Vector2(u, v); 26.359 + 26.360 + if(i < usub && j < vsub) { 26.361 + int idx = i * vverts + j; 26.362 + 26.363 + *idxarr++ = idx; 26.364 + *idxarr++ = idx + vverts + 1; 26.365 + *idxarr++ = idx + 1; 26.366 + 26.367 + *idxarr++ = idx; 26.368 + *idxarr++ = idx + vverts; 26.369 + *idxarr++ = idx + vverts + 1; 26.370 + } 26.371 + 26.372 + v += dv; 26.373 + } 26.374 + u += du; 26.375 + } 26.376 +}
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/src/meshgen.h Thu Nov 14 05:27:09 2013 +0200 27.3 @@ -0,0 +1,11 @@ 27.4 +#ifndef MESHGEN_H_ 27.5 +#define MESHGEN_H_ 27.6 + 27.7 +class Mesh; 27.8 + 27.9 +void gen_sphere(Mesh *mesh, float rad, int usub, int vsub, float urange = 1.0, float vrange = 1.0); 27.10 +void gen_cylinder(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub = 0, float urange = 1.0, float vrange = 1.0); 27.11 +void gen_cone(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub = 0, float urange = 1.0, float vrange = 1.0); 27.12 +void gen_plane(Mesh *mesh, float width, float height, int usub = 1, int vsub = 1); 27.13 + 27.14 +#endif // MESHGEN_H_
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 28.2 +++ b/src/object.cc Thu Nov 14 05:27:09 2013 +0200 28.3 @@ -0,0 +1,284 @@ 28.4 +#include <float.h> 28.5 +#include "object.h" 28.6 +#include "opengl.h" 28.7 +#include "unistate.h" 28.8 +#include "logger.h" 28.9 + 28.10 +static void destroy_all_rec(XFormNode *node); 28.11 +static void get_all_meshes_rec(XFormNode *node, std::list<Mesh*> *reslist); 28.12 + 28.13 +DrawMode Object::draw_mode = DRAW_DEFAULT; 28.14 + 28.15 +Object::Object() 28.16 +{ 28.17 + mesh = 0; 28.18 +} 28.19 + 28.20 +void Object::destroy_all() 28.21 +{ 28.22 + destroy_all_rec(this); 28.23 +} 28.24 + 28.25 +static void destroy_all_rec(XFormNode *node) 28.26 +{ 28.27 + if(!node) { 28.28 + return; 28.29 + } 28.30 + 28.31 + for(int i=0; i<node->get_children_count(); i++) { 28.32 + destroy_all_rec(node->get_child(i)); 28.33 + } 28.34 + delete node; 28.35 +} 28.36 + 28.37 +void Object::set_mesh(Mesh *m) 28.38 +{ 28.39 + mesh = m; 28.40 +} 28.41 + 28.42 +Mesh *Object::get_mesh() 28.43 +{ 28.44 + return mesh; 28.45 +} 28.46 + 28.47 +const Mesh *Object::get_mesh() const 28.48 +{ 28.49 + return mesh; 28.50 +} 28.51 + 28.52 +std::list<Mesh*> Object::get_all_meshes() 28.53 +{ 28.54 + std::list<Mesh*> meshes; 28.55 + get_all_meshes_rec(this, &meshes); 28.56 + return meshes; 28.57 +} 28.58 + 28.59 +std::list<const Mesh*> Object::get_all_meshes() const 28.60 +{ 28.61 + std::list<const Mesh*> meshes; 28.62 + get_all_meshes_rec((Object*)this, (std::list<Mesh*>*)&meshes); 28.63 + return meshes; 28.64 +} 28.65 + 28.66 +static void get_all_meshes_rec(XFormNode *node, std::list<Mesh*> *reslist) 28.67 +{ 28.68 + if(!node) { 28.69 + return; 28.70 + } 28.71 + 28.72 + Object *obj = dynamic_cast<Object*>(node); 28.73 + if(obj) { 28.74 + Mesh *mesh = obj->get_mesh(); 28.75 + if(mesh) { 28.76 + reslist->push_back(mesh); 28.77 + } 28.78 + } 28.79 + 28.80 + for(int i=0; i<node->get_children_count(); i++) { 28.81 + get_all_meshes_rec(node->get_child(i), reslist); 28.82 + } 28.83 +} 28.84 + 28.85 +AABox Object::get_aabbox() const 28.86 +{ 28.87 + AABox box; 28.88 + 28.89 + if(mesh) { 28.90 + box = mesh->get_aabbox(); 28.91 + } else { 28.92 + box.min = Vector3(FLT_MAX, FLT_MAX, FLT_MAX); 28.93 + box.max = -box.min; 28.94 + } 28.95 + 28.96 + int num_children = get_children_count(); 28.97 + for(int i=0; i<num_children; i++) { 28.98 + const Object *obj = dynamic_cast<const Object*>(get_child(i)); 28.99 + if(obj) { 28.100 + AABox child_box = obj->get_aabbox(); 28.101 + box.set_union(&box, &child_box); 28.102 + } 28.103 + } 28.104 + return box; 28.105 +} 28.106 + 28.107 +Sphere Object::get_bsphere() const 28.108 +{ 28.109 + Sphere sph; 28.110 + bool valid = false; 28.111 + 28.112 + if(mesh) { 28.113 + sph = mesh->get_bsphere(); 28.114 + valid = true; 28.115 + } else { 28.116 + sph.radius = 0.0; 28.117 + } 28.118 + 28.119 + int num_children = get_children_count(); 28.120 + for(int i=0; i<num_children; i++) { 28.121 + const Object *obj = dynamic_cast<const Object*>(get_child(i)); 28.122 + if(obj) { 28.123 + Sphere child_sph = obj->get_bsphere(); 28.124 + if(valid) { 28.125 + sph.set_union(&sph, &child_sph); 28.126 + } else { 28.127 + sph = child_sph; 28.128 + valid = true; 28.129 + } 28.130 + } 28.131 + } 28.132 + 28.133 + return sph; 28.134 +} 28.135 + 28.136 +/*static const char *attr_name[] = { 28.137 + "attr_vertex", 28.138 + "attr_normal", 28.139 + "attr_tangent", 28.140 + "attr_texcoord", 28.141 + "attr_boneweights", 28.142 + "attr_boneidx" 28.143 +};*/ 28.144 + 28.145 +void Object::draw(long msec) const 28.146 +{ 28.147 + Matrix4x4 xform; 28.148 + get_xform(msec, &xform); 28.149 + 28.150 + set_world_matrix(xform); 28.151 + 28.152 + if(mesh) { 28.153 + /*unsigned int prog = sdrprog; 28.154 + 28.155 + if(mesh->get_bones_count() > 0) { 28.156 + prog = sdrprog_skin; 28.157 + } 28.158 + 28.159 + glUseProgram(prog); 28.160 + // get all the attribute locations 28.161 + for(int i=0; i<NUM_MESH_ATTR; i++) { 28.162 + int loc = glGetAttribLocation(prog, attr_name[i]); 28.163 + if(loc != -1) { 28.164 + Mesh::set_attrib_location(i, loc); 28.165 + } 28.166 + } 28.167 + 28.168 + setup_bones(msec); 28.169 + 28.170 + glUseProgram(prog);*/ 28.171 + 28.172 + material.setup(); 28.173 + setup_unistate(); // set all state uniforms 28.174 + 28.175 + switch(Object::draw_mode) { 28.176 + case DRAW_WIREFRAME: 28.177 + mesh->draw_wire(); 28.178 + break; 28.179 + 28.180 + case DRAW_VERTICES: 28.181 + mesh->draw_vertices(); 28.182 + break; 28.183 + 28.184 + case DRAW_DEFAULT: 28.185 + default: 28.186 + mesh->draw(); 28.187 + } 28.188 + } 28.189 + 28.190 + int num_children = get_children_count(); 28.191 + for(int i=0; i<num_children; i++) { 28.192 + const Object *obj = dynamic_cast<const Object*>(get_child(i)); 28.193 + if(obj) { 28.194 + obj->draw(msec); 28.195 + } 28.196 + } 28.197 +} 28.198 + 28.199 + 28.200 +bool Object::intersect(const Ray &inray, HitPoint *hit) const 28.201 +{ 28.202 + Ray ray = inray; 28.203 + Matrix4x4 xform, inv_xform; 28.204 + get_xform(ray.time, &xform/*, &inv_xform*/); 28.205 + ray.transform(xform.inverse()); // TODO find out what's wrong with get_xform's inv_xform and use that 28.206 + 28.207 + HitPoint nearest_hit; 28.208 + nearest_hit.dist = FLT_MAX; 28.209 + nearest_hit.obj = 0; 28.210 + 28.211 + if(mesh) { 28.212 + if(mesh->intersect(ray, hit ? &nearest_hit : 0)) { 28.213 + if(!hit) { 28.214 + return true; 28.215 + } 28.216 + 28.217 + if(Mesh::get_intersect_mode() & ISECT_FACE) { 28.218 + Triangle *face = (Triangle*)nearest_hit.obj; 28.219 + face->transform(xform); 28.220 + } else if(Mesh::get_intersect_mode() & ISECT_VERTICES) { 28.221 + Vector3 *v = (Vector3*)nearest_hit.obj; 28.222 + v->transform(xform); 28.223 + } else { 28.224 + nearest_hit.obj = this; 28.225 + } 28.226 + } 28.227 + } 28.228 + 28.229 + int num_children = get_children_count(); 28.230 + for(int i=0; i<num_children; i++) { 28.231 + const Object *obj = dynamic_cast<const Object*>(get_child(i)); 28.232 + 28.233 + HitPoint chit; 28.234 + if(obj && obj->intersect(inray, hit ? &chit : 0)) { 28.235 + if(!hit) { 28.236 + return true; 28.237 + } 28.238 + 28.239 + if(chit.dist < nearest_hit.dist) { 28.240 + nearest_hit = chit; 28.241 + } 28.242 + } 28.243 + } 28.244 + 28.245 + if(nearest_hit.obj) { 28.246 + if(hit) { 28.247 + *hit = nearest_hit; 28.248 + } 28.249 + return true; 28.250 + } 28.251 + return false; 28.252 +} 28.253 + 28.254 + 28.255 +bool Object::setup_bones(long msec) const 28.256 +{ 28.257 + int num_bones; 28.258 + if(!mesh || !(num_bones = mesh->get_bones_count())) { 28.259 + return false; 28.260 + } 28.261 + 28.262 + /*char uniname[32]; 28.263 + 28.264 + for(int i=0; i<num_bones; i++) { 28.265 + const XFormNode *bone = mesh->get_bone(i); 28.266 + 28.267 + Matrix4x4 xform; 28.268 + bone->get_xform(msec, &xform); 28.269 + 28.270 + xform = xform * bone->get_bone_matrix(); 28.271 + 28.272 + sprintf(uniname, "bone_xform[%d]", i); 28.273 + int loc = glGetUniformLocation(sdrprog_skin, uniname); 28.274 + if(loc == -1) { 28.275 + return false; 28.276 + } 28.277 + glUniformMatrix4fv(loc, 1, GL_TRUE, xform[0]); 28.278 + }*/ 28.279 + return true; 28.280 +} 28.281 + 28.282 +DrawMode Object::set_draw_mode(DrawMode mode) 28.283 +{ 28.284 + DrawMode prev = Object::draw_mode; 28.285 + Object::draw_mode = mode; 28.286 + return prev; 28.287 +}
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 29.2 +++ b/src/object.h Thu Nov 14 05:27:09 2013 +0200 29.3 @@ -0,0 +1,51 @@ 29.4 +#ifndef OBJECT_H_ 29.5 +#define OBJECT_H_ 29.6 + 29.7 +#include <list> 29.8 +#include "xform_node.h" 29.9 +#include "mesh.h" 29.10 +#include "material.h" 29.11 + 29.12 +enum DrawMode { 29.13 + DRAW_DEFAULT, 29.14 + DRAW_WIREFRAME, 29.15 + DRAW_VERTICES 29.16 +}; 29.17 + 29.18 + 29.19 +class Object : public XFormNode { 29.20 +private: 29.21 + Mesh *mesh; ///< no ownership, just keeping the pointer around 29.22 + static DrawMode draw_mode; 29.23 + 29.24 + bool setup_bones(long msec) const; 29.25 + 29.26 +public: 29.27 + Material material; 29.28 + 29.29 + Object(); 29.30 + 29.31 + /// destroy this object and all the hierarchy of objects hanging below it 29.32 + void destroy_all(); 29.33 + 29.34 + void set_mesh(Mesh *m); 29.35 + Mesh *get_mesh(); 29.36 + const Mesh *get_mesh() const; 29.37 + 29.38 + /// get all the meshes of the subtree rooted in this object @{ 29.39 + std::list<Mesh*> get_all_meshes(); 29.40 + std::list<const Mesh*> get_all_meshes() const; 29.41 + /// @} 29.42 + 29.43 + AABox get_aabbox() const; 29.44 + Sphere get_bsphere() const; 29.45 + 29.46 + void draw(long msec = 0) const; 29.47 + 29.48 + bool intersect(const Ray &ray, HitPoint *hit = 0) const; 29.49 + 29.50 + /// this is mostly for tools, to allow drawing only the wireframe or vertices 29.51 + static DrawMode set_draw_mode(DrawMode mode); 29.52 +}; 29.53 + 29.54 +#endif // OBJECT_H_
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 30.2 +++ b/src/opengl.cc Thu Nov 14 05:27:09 2013 +0200 30.3 @@ -0,0 +1,29 @@ 30.4 +#include "opengl.h" 30.5 + 30.6 +void init_opengl() 30.7 +{ 30.8 +#ifdef __GLEW_H__ 30.9 + glewInit(); 30.10 +#endif 30.11 +} 30.12 + 30.13 +const char *strglerr(int err) 30.14 +{ 30.15 + static const char *errnames[] = { 30.16 + "GL_INVALID_ENUM", 30.17 + "GL_INVALID_VALUE", 30.18 + "GL_INVALID_OPERATION", 30.19 + "GL_STACK_OVERFLOW", 30.20 + "GL_STACK_UNDERFLOW", 30.21 + "GL_OUT_OF_MEMORY", 30.22 + "GL_INVALID_FRAMEBUFFER_OPERATION" 30.23 + }; 30.24 + 30.25 + if(!err) { 30.26 + return "GL_NO_ERROR"; 30.27 + } 30.28 + if(err < GL_INVALID_ENUM || err > GL_OUT_OF_MEMORY) { 30.29 + return "<invalid gl error>"; 30.30 + } 30.31 + return errnames[err - GL_INVALID_ENUM]; 30.32 +}
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 31.2 +++ b/src/opengl.h Thu Nov 14 05:27:09 2013 +0200 31.3 @@ -0,0 +1,71 @@ 31.4 +#ifndef OPENGL_H_ 31.5 +#define OPENGL_H_ 31.6 + 31.7 +#include <stdlib.h> 31.8 + 31.9 +#ifdef __APPLE__ 31.10 +#include "TargetConditionals.h" 31.11 + 31.12 +#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR 31.13 +/* iOS */ 31.14 +#include <OpenGLES/ES2/gl.h> 31.15 +#include <OpenGLES/ES2/glext.h> 31.16 + 31.17 +#define GL_CLAMP GL_CLAMP_TO_EDGE 31.18 +#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES 31.19 + 31.20 +#undef USE_OLDGL 31.21 + 31.22 +#define GL_WRITE_ONLY GL_WRITE_ONLY_OES 31.23 +#define glMapBuffer glMapBufferOES 31.24 +#define glUnmapBuffer glUnmapBufferOES 31.25 + 31.26 +#else 31.27 +/* MacOS X */ 31.28 +#include <GL/glew.h> 31.29 +#include <GLUT/glut.h> 31.30 + 31.31 +#define USE_OLDGL 31.32 +#endif 31.33 + 31.34 +#else 31.35 +/* UNIX or Windows */ 31.36 +#include <GL/glew.h> 31.37 +#include <GL/glut.h> 31.38 + 31.39 +#define USE_OLDGL 31.40 +#endif 31.41 + 31.42 +#ifndef GL_RGB16F 31.43 +#define GL_RGB16F 0x881b 31.44 +#endif 31.45 +#ifndef GL_RGBA16F 31.46 +#define GL_RGBA16F 0x881a 31.47 +#endif 31.48 +#ifndef GL_RGB32F 31.49 +#define GL_RGB32F 0x8815 31.50 +#endif 31.51 +#ifndef GL_RGBA32F 31.52 +#define GL_RGBA32F 0x8814 31.53 +#endif 31.54 +#ifndef GL_LUMINANCE16F 31.55 +#define GL_LUMINANCE16F 0x881e 31.56 +#endif 31.57 +#ifndef GL_LUMINANCE32F 31.58 +#define GL_LUMINANCE32F 0x8818 31.59 +#endif 31.60 + 31.61 +#define CHECKGLERR \ 31.62 + do { \ 31.63 + int err = glGetError(); \ 31.64 + if(err) { \ 31.65 + fprintf(stderr, "%s:%d: OpenGL error 0x%x: %s\n", __FILE__, __LINE__, err, strglerr(err)); \ 31.66 + abort(); \ 31.67 + } \ 31.68 + } while(0) 31.69 + 31.70 +void init_opengl(); 31.71 + 31.72 +const char *strglerr(int err); 31.73 + 31.74 +#endif // OPENGL_H_
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 32.2 +++ b/src/psyspp.cc Thu Nov 14 05:27:09 2013 +0200 32.3 @@ -0,0 +1,459 @@ 32.4 +#include <limits.h> 32.5 +#include "psyspp.h" 32.6 +#include "sdrman.h" 32.7 +#include "logger.h" 32.8 +#include "mesh.h" // just for the attrib enums 32.9 +#include "unistate.h" 32.10 +#include "datapath.h" 32.11 +#include "texman.h" 32.12 +#include "texgen.h" 32.13 + 32.14 +static void pdraw_start(const psys_emitter *em, void *cls); 32.15 +static void pdraw(const psys_emitter *em, const psys_particle *part, void *cls); 32.16 +static void pdraw_end(const psys_emitter *em, void *cls); 32.17 + 32.18 +static unsigned int psys_load_texture(const char *fname, void *cls); 32.19 + 32.20 +ParticleSystemAttributes::ParticleSystemAttributes() 32.21 +{ 32.22 + tex = 0; 32.23 + own_psattr = true; 32.24 + psattr = new psys_attributes; 32.25 + psys_init_attr(psattr); 32.26 +} 32.27 + 32.28 +ParticleSystemAttributes::ParticleSystemAttributes(psys_attributes *psattr) 32.29 +{ 32.30 + tex = 0; 32.31 + own_psattr = false; 32.32 + this->psattr = psattr; 32.33 +} 32.34 + 32.35 +ParticleSystemAttributes::~ParticleSystemAttributes() 32.36 +{ 32.37 + if(own_psattr) { 32.38 + psys_destroy_attr(psattr); 32.39 + delete psattr; 32.40 + } 32.41 +} 32.42 + 32.43 +ParticleSystemAttributes::ParticleSystemAttributes(const ParticleSystemAttributes &rhs) 32.44 +{ 32.45 + own_psattr = true; 32.46 + tex = rhs.tex; 32.47 + psattr = new psys_attributes; 32.48 + psys_init_attr(psattr); 32.49 + 32.50 + psys_copy_attr(psattr, rhs.psattr); 32.51 +} 32.52 + 32.53 +ParticleSystemAttributes &ParticleSystemAttributes::operator =(const ParticleSystemAttributes &rhs) 32.54 +{ 32.55 + if(&rhs != this) { 32.56 + tex = rhs.tex; 32.57 + psys_copy_attr(psattr, rhs.psattr); 32.58 + } 32.59 + return *this; 32.60 +} 32.61 + 32.62 +bool ParticleSystemAttributes::load(const char *fname) 32.63 +{ 32.64 + psys_texture_loader(psys_load_texture, 0, this); 32.65 + return psys_load_attr(psattr, datafile_path(fname).c_str()) != -1; 32.66 +} 32.67 + 32.68 +bool ParticleSystemAttributes::load(FILE *fp) 32.69 +{ 32.70 + psys_texture_loader(psys_load_texture, 0, this); 32.71 + return psys_load_attr_stream(psattr, fp) != -1; 32.72 +} 32.73 + 32.74 +bool ParticleSystemAttributes::save(const char *fname) const 32.75 +{ 32.76 + return psys_save_attr(psattr, fname) != -1; 32.77 +} 32.78 + 32.79 +bool ParticleSystemAttributes::save(FILE *fp) const 32.80 +{ 32.81 + return psys_save_attr_stream(psattr, fp) != -1; 32.82 +} 32.83 + 32.84 +void ParticleSystemAttributes::set_part_color(const Vector3 &color, float t) 32.85 +{ 32.86 + psys_set_value3(&psattr->part_attr.color, (anm_time_t)(t * 1000.0), v3_cons(color.x, color.y, color.z)); 32.87 +} 32.88 + 32.89 +void ParticleSystemAttributes::set_part_alpha(float alpha, float t) 32.90 +{ 32.91 + psys_set_value(&psattr->part_attr.alpha, (anm_time_t)(t * 1000.0), alpha); 32.92 +} 32.93 + 32.94 +void ParticleSystemAttributes::set_part_scale(float size, float t) 32.95 +{ 32.96 + psys_set_value(&psattr->part_attr.size, (anm_time_t)(t * 1000.0), size); 32.97 +} 32.98 + 32.99 + 32.100 +// emmiter attributes 32.101 +void ParticleSystemAttributes::set_texture(Texture *tex) 32.102 +{ 32.103 + this->tex = tex; 32.104 + psattr->tex = tex->get_id(); 32.105 +} 32.106 + 32.107 +Texture *ParticleSystemAttributes::get_texture() const 32.108 +{ 32.109 + return tex; 32.110 +} 32.111 + 32.112 +void ParticleSystemAttributes::set_spawn_range(const Vector3 &range, long tm) 32.113 +{ 32.114 + psys_set_value3(&psattr->spawn_range, ANM_MSEC2TM(tm), v3_cons(range.x, range.y, range.z)); 32.115 +} 32.116 + 32.117 +void ParticleSystemAttributes::set_spawn_rate(float rate, long tm) 32.118 +{ 32.119 + psys_set_value(&psattr->rate, ANM_MSEC2TM(tm), rate); 32.120 +} 32.121 + 32.122 +float ParticleSystemAttributes::get_spawn_rate(long tm) const 32.123 +{ 32.124 + return psys_get_value(&psattr->rate, ANM_MSEC2TM(tm)); 32.125 +} 32.126 + 32.127 +void ParticleSystemAttributes::set_life(float life, float range, long tm) 32.128 +{ 32.129 + psys_set_anm_rnd(&psattr->life, ANM_MSEC2TM(tm), life, range); 32.130 +} 32.131 + 32.132 +void ParticleSystemAttributes::set_size(float sz, float range, long tm) 32.133 +{ 32.134 + psys_set_anm_rnd(&psattr->size, ANM_MSEC2TM(tm), sz, range); 32.135 +} 32.136 + 32.137 +void ParticleSystemAttributes::set_spawn_dir(const Vector3 &dir, const Vector3 &range, long tm) 32.138 +{ 32.139 + psys_set_anm_rnd3(&psattr->dir, ANM_MSEC2TM(tm), v3_cons(dir.x, dir.y, dir.z), v3_cons(range.x, range.y, range.z)); 32.140 +} 32.141 + 32.142 +void ParticleSystemAttributes::set_gravity(const Vector3 &grav, long tm) 32.143 +{ 32.144 + psys_set_value3(&psattr->grav, ANM_MSEC2TM(tm), v3_cons(grav.x, grav.y, grav.z)); 32.145 +} 32.146 + 32.147 +void ParticleSystemAttributes::set_drag(float drag) 32.148 +{ 32.149 + psattr->drag = drag; 32.150 +} 32.151 + 32.152 +void ParticleSystemAttributes::set_particle_limit(int lim) 32.153 +{ 32.154 + psattr->max_particles = lim; 32.155 +} 32.156 + 32.157 + 32.158 +// ---- ParticleSystem ---- 32.159 + 32.160 +ParticleSystem::ParticleSystem() 32.161 + : attr(&psys.attr) 32.162 +{ 32.163 + psys_init(&psys); 32.164 + psys_draw_func(&psys, pdraw, pdraw_start, pdraw_end, (void*)this); 32.165 + start_time = LONG_MIN; 32.166 + last_upd_time = LONG_MIN; 32.167 +} 32.168 + 32.169 +ParticleSystem::~ParticleSystem() 32.170 +{ 32.171 + psys_destroy(&psys); 32.172 +} 32.173 + 32.174 +void ParticleSystem::set_start_time(long tm) 32.175 +{ 32.176 + start_time = tm; 32.177 +} 32.178 + 32.179 +bool ParticleSystem::is_active() const 32.180 +{ 32.181 + float rate = attr.get_spawn_rate(last_upd_time); 32.182 + return psys.pcount > 0 || last_upd_time == 0;// || rate > 0.0; 32.183 +} 32.184 + 32.185 +ParticleSystemAttributes *ParticleSystem::get_attr() 32.186 +{ 32.187 + return &attr; 32.188 +} 32.189 + 32.190 +const ParticleSystemAttributes *ParticleSystem::get_attr() const 32.191 +{ 32.192 + return &attr; 32.193 +} 32.194 + 32.195 +void ParticleSystem::set_attr(const ParticleSystemAttributes &pattr) 32.196 +{ 32.197 + attr = pattr; 32.198 +} 32.199 + 32.200 +bool ParticleSystem::load(const char *fname) 32.201 +{ 32.202 + psys_texture_loader(psys_load_texture, 0, &attr); 32.203 + return attr.load(fname); 32.204 +} 32.205 + 32.206 +bool ParticleSystem::save(const char *fname) const 32.207 +{ 32.208 + return attr.save(fname); 32.209 +} 32.210 + 32.211 +void ParticleSystem::update(long tm) 32.212 +{ 32.213 + if(start_time > LONG_MIN) { 32.214 + tm -= start_time; 32.215 + } 32.216 + 32.217 + Matrix4x4 xform; 32.218 + get_xform(tm, &xform); 32.219 + 32.220 + Vector3 pos = Vector3(0, 0, 0).transformed(xform); 32.221 + 32.222 + psys_set_pos(&psys, v3_cons(pos.x, pos.y, pos.z), 0); 32.223 + psys_update(&psys, (double)tm / 1000.0); 32.224 + 32.225 + last_upd_time = tm; 32.226 +} 32.227 + 32.228 +void ParticleSystem::draw() const 32.229 +{ 32.230 + psys_draw(&psys); 32.231 +} 32.232 + 32.233 +// ---- particle drawing ---- 32.234 +struct PVertex { 32.235 + Vector4 color; 32.236 + Vector3 pos; 32.237 + Vector2 texcoord; 32.238 +}; 32.239 + 32.240 + 32.241 +#define USE_VBO 32.242 +#define USE_IBO 32.243 + 32.244 + 32.245 +#define MAX_DRAW_PART 256 32.246 +#define MAX_PVERTS (MAX_DRAW_PART * 4) 32.247 +static PVertex *pvarr, *pvptr; 32.248 + 32.249 +// double-buffered vbo set, write on one, while drawing from the other 32.250 + 32.251 +#ifdef USE_VBO 32.252 +static unsigned int vbo[2]; 32.253 +static int cur_buf; // current write vbo 32.254 +#endif 32.255 +static int num_buffered; // number of particles bufferd, will flush when >= MAX_DRAW_PART 32.256 + 32.257 +// ok so the index array is constant, regardless of the particle system 32.258 +// so this is a static index buffer created in init_particle_draw which should 32.259 +// be called once. 32.260 +#define MAX_PVIDX (MAX_DRAW_PART * 6) 32.261 +#ifdef USE_IBO 32.262 +static unsigned int ibo; 32.263 +#endif 32.264 +unsigned int *pvidx; 32.265 + 32.266 +static ShaderProg *psdr; // particle shader 32.267 +static Texture2D *blank_tex; 32.268 + 32.269 +static inline void init_particle_draw() 32.270 +{ 32.271 + static bool done_init; 32.272 + if(done_init) { 32.273 + return; // once 32.274 + } 32.275 + 32.276 + pvidx = new unsigned int[MAX_PVIDX]; 32.277 + unsigned int *ptr = pvidx; 32.278 + 32.279 + static const unsigned int idxoffs[] = { 0, 1, 2, 0, 2, 3 }; 32.280 + 32.281 + for(int i=0; i<MAX_DRAW_PART; i++) { 32.282 + for(int j=0; j<6; j++) { 32.283 + *ptr++ = i * 4 + idxoffs[j]; 32.284 + } 32.285 + } 32.286 + 32.287 +#ifdef USE_IBO 32.288 + glGenBuffers(1, &ibo); 32.289 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 32.290 + glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_PVIDX * sizeof *pvidx, pvidx, GL_STATIC_DRAW); 32.291 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 32.292 + 32.293 + delete [] pvidx; 32.294 +#endif 32.295 + 32.296 +#ifdef USE_VBO 32.297 + // create the stream vertex buffers (double buffering) 32.298 + glGenBuffers(2, vbo); 32.299 + for(int i=0; i<2; i++) { 32.300 + glBindBuffer(GL_ARRAY_BUFFER, vbo[i]); 32.301 + glBufferData(GL_ARRAY_BUFFER, MAX_PVERTS * sizeof(PVertex), 0, GL_STREAM_DRAW); 32.302 + } 32.303 + glBindBuffer(GL_ARRAY_BUFFER, 0); 32.304 +#else 32.305 + pvarr = new PVertex[MAX_PVERTS]; 32.306 + pvptr = pvarr; 32.307 +#endif 32.308 + 32.309 + // load shader program 32.310 + if(!(psdr = get_sdrprog("psdr.v.glsl", "psdr.p.glsl"))) { 32.311 + error_log("failed to load particle shader!\n"); 32.312 + } 32.313 + 32.314 + // create empty texture 32.315 + Image *img = texgen_solid(8, 8, Vector4(1, 1, 1, 1)); 32.316 + blank_tex = new Texture2D; 32.317 + blank_tex->set_image(*img); 32.318 + delete img; 32.319 + 32.320 + done_init = true; 32.321 +} 32.322 + 32.323 +static void pdraw_flush() 32.324 +{ 32.325 +#ifdef USE_VBO 32.326 + // assuming vbo[cur_buf] is bound 32.327 + glUnmapBuffer(GL_ARRAY_BUFFER); 32.328 +#endif 32.329 + 32.330 + // draw from the bound buffer 6 indices per particle 32.331 +#ifdef USE_IBO 32.332 + glDrawElements(GL_TRIANGLES, num_buffered * 6, GL_UNSIGNED_INT, 0); 32.333 +#else 32.334 + glDrawElements(GL_TRIANGLES, num_buffered * 6, GL_UNSIGNED_INT, pvidx); 32.335 +#endif 32.336 + num_buffered = 0; 32.337 + 32.338 +#ifdef USE_VBO 32.339 + // map the next buffer (write buffer) while the previous is drawing 32.340 + cur_buf = (cur_buf + 1) & 1; 32.341 + glBindBuffer(GL_ARRAY_BUFFER, vbo[cur_buf]); 32.342 + pvarr = (PVertex*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); 32.343 +#endif 32.344 + pvptr = pvarr; 32.345 +} 32.346 + 32.347 +static void pdraw_start(const psys_emitter *em, void *cls) 32.348 +{ 32.349 + ParticleSystem *ps = (ParticleSystem*)cls; 32.350 + 32.351 + init_particle_draw(); 32.352 + 32.353 + num_buffered = 0; 32.354 + 32.355 +#ifdef USE_IBO 32.356 + // bind the particle index buffer which is static 32.357 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 32.358 +#endif 32.359 + 32.360 +#ifdef USE_VBO 32.361 + // map the current write buffer 32.362 + glBindBuffer(GL_ARRAY_BUFFER, vbo[cur_buf]); 32.363 + pvarr = (PVertex*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); 32.364 +#endif 32.365 + pvptr = pvarr; 32.366 + 32.367 + Texture *tex = ps->get_attr()->get_texture(); 32.368 + if(tex) { 32.369 + tex->bind(); 32.370 + } else { 32.371 + blank_tex->bind(); 32.372 + } 32.373 + psdr->bind(); 32.374 + 32.375 + glDisable(GL_DEPTH_TEST); 32.376 + glDisable(GL_CULL_FACE); 32.377 + glEnable(GL_BLEND); 32.378 + glBlendFunc(GL_SRC_ALPHA, GL_ONE); 32.379 + glDepthMask(0); 32.380 + 32.381 + glEnableVertexAttribArray(MESH_ATTR_VERTEX); 32.382 + glEnableVertexAttribArray(MESH_ATTR_COLOR); 32.383 + glEnableVertexAttribArray(MESH_ATTR_TEXCOORD); 32.384 + 32.385 +#ifdef USE_VBO 32.386 + glVertexAttribPointer(MESH_ATTR_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof *pvarr, (void*)((char*)&pvarr->pos - (char*)pvarr)); 32.387 + glVertexAttribPointer(MESH_ATTR_COLOR, 4, GL_FLOAT, GL_TRUE, sizeof *pvarr, (void*)((char*)&pvarr->color - (char*)pvarr)); 32.388 + glVertexAttribPointer(MESH_ATTR_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof *pvarr, (void*)((char*)&pvarr->texcoord - (char*)pvarr)); 32.389 +#else 32.390 + glVertexAttribPointer(MESH_ATTR_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof *pvarr, (void*)&pvarr->pos); 32.391 + glVertexAttribPointer(MESH_ATTR_COLOR, 4, GL_FLOAT, GL_TRUE, sizeof *pvarr, (void*)&pvarr->color); 32.392 + glVertexAttribPointer(MESH_ATTR_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof *pvarr, (void*)&pvarr->texcoord); 32.393 +#endif 32.394 +} 32.395 + 32.396 +static void pdraw(const psys_emitter *em, const psys_particle *part, void *cls) 32.397 +{ 32.398 + ParticleSystem *ps = (ParticleSystem*)cls; 32.399 + 32.400 + static const Vector3 pv[] = { 32.401 + Vector3(-0.5, -0.5, 0), 32.402 + Vector3(0.5, -0.5, 0), 32.403 + Vector3(0.5, 0.5, 0), 32.404 + Vector3(-0.5, 0.5, 0) 32.405 + }; 32.406 + static const Vector2 tex[] = { 32.407 + Vector2(0, 0), Vector2(0, 1), Vector2(1, 1), Vector2(1, 0) 32.408 + }; 32.409 + Vector4 color = Vector4(part->color.x, part->color.y, part->color.z, part->alpha); 32.410 + 32.411 + for(int i=0; i<4; i++) { 32.412 + pvptr->color = color; 32.413 + pvptr->pos = pv[i] * part->size + part->pos; 32.414 + pvptr->texcoord = tex[i]; 32.415 + pvptr++; 32.416 + } 32.417 + // XXX we don't need billboarding for this game, so don't bother 32.418 + 32.419 + // if we reached the maximum number of buffered particles, draw them 32.420 + if(++num_buffered >= MAX_DRAW_PART) { 32.421 + pdraw_flush(); // this will reset the counter 32.422 + } 32.423 +} 32.424 + 32.425 +static void pdraw_end(const psys_emitter *em, void *cls) 32.426 +{ 32.427 + // if we have leftover particles buffered, draw them before returning 32.428 + if(num_buffered) { 32.429 + pdraw_flush(); 32.430 + } 32.431 + 32.432 + // cleanup 32.433 + glDisableVertexAttribArray(MESH_ATTR_VERTEX); 32.434 + glDisableVertexAttribArray(MESH_ATTR_COLOR); 32.435 + glDisableVertexAttribArray(MESH_ATTR_TEXCOORD); 32.436 + 32.437 +#ifdef USE_VBO 32.438 + glUnmapBuffer(GL_ARRAY_BUFFER); 32.439 + glBindBuffer(GL_ARRAY_BUFFER, 0); 32.440 +#endif 32.441 +#ifdef USE_IBO 32.442 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 32.443 +#endif 32.444 + 32.445 + glDepthMask(1); 32.446 + glDisable(GL_BLEND); 32.447 + 32.448 + glEnable(GL_DEPTH_TEST); 32.449 + glEnable(GL_CULL_FACE); 32.450 +} 32.451 + 32.452 +static unsigned int psys_load_texture(const char *fname, void *cls) 32.453 +{ 32.454 + ParticleSystemAttributes *attr = (ParticleSystemAttributes*)cls; 32.455 + 32.456 + Texture *tex = texset.get(fname); 32.457 + if(tex) { 32.458 + attr->set_texture(tex); 32.459 + return tex->get_id(); 32.460 + } 32.461 + return 0; 32.462 +}
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 33.2 +++ b/src/psyspp.h Thu Nov 14 05:27:09 2013 +0200 33.3 @@ -0,0 +1,79 @@ 33.4 +#ifndef PSYSPP_H_ 33.5 +#define PSYSPP_H_ 33.6 + 33.7 +#include "xform_node.h" 33.8 +#include "texture.h" 33.9 +#include <psys/psys.h> 33.10 + 33.11 +class ParticleSystemAttributes { 33.12 +private: 33.13 + Texture *tex; 33.14 + psys_attributes *psattr; 33.15 + bool own_psattr; 33.16 + 33.17 +public: 33.18 + ParticleSystemAttributes(); 33.19 + ParticleSystemAttributes(psys_attributes *psattr); 33.20 + ~ParticleSystemAttributes(); 33.21 + 33.22 + ParticleSystemAttributes(const ParticleSystemAttributes &rhs); 33.23 + ParticleSystemAttributes &operator =(const ParticleSystemAttributes &rhs); 33.24 + 33.25 + bool load(const char *fname); 33.26 + bool load(FILE *fp); 33.27 + bool save(const char *fname) const; 33.28 + bool save(FILE *fp) const; 33.29 + 33.30 + // particle attributes 33.31 + void set_part_color(const Vector3 &color, float t = 0); 33.32 + void set_part_alpha(float alpha, float t = 0); 33.33 + void set_part_scale(float size, float t = 0); 33.34 + 33.35 + // emmiter attributes 33.36 + void set_texture(Texture *tex); 33.37 + Texture *get_texture() const; 33.38 + 33.39 + void set_spawn_range(const Vector3 &range, long tm = 0); 33.40 + 33.41 + void set_spawn_rate(float rate, long tm = 0); 33.42 + float get_spawn_rate(long tm = 0) const; 33.43 + 33.44 + void set_life(float life, float range = 0.0, long tm = 0); 33.45 + void set_size(float sz, float range = 0.0, long tm = 0); 33.46 + void set_spawn_dir(const Vector3 &dir, const Vector3 &range = Vector3(0, 0, 0), long tm = 0); 33.47 + 33.48 + void set_gravity(const Vector3 &grav, long tm = 0); 33.49 + void set_drag(float drag); 33.50 + 33.51 + void set_particle_limit(int lim); 33.52 +}; 33.53 + 33.54 +class ParticleSystem : public XFormNode { 33.55 +private: 33.56 + psys_emitter psys; 33.57 + ParticleSystemAttributes attr; 33.58 + 33.59 + long start_time; // subtracted from all time calculations 33.60 + long last_upd_time; 33.61 + 33.62 +public: 33.63 + ParticleSystem(); 33.64 + ~ParticleSystem(); 33.65 + 33.66 + void set_start_time(long tm); 33.67 + 33.68 + bool is_active() const; 33.69 + 33.70 + ParticleSystemAttributes *get_attr(); 33.71 + const ParticleSystemAttributes *get_attr() const; 33.72 + 33.73 + void set_attr(const ParticleSystemAttributes &pattr); 33.74 + 33.75 + bool load(const char *fname); 33.76 + bool save(const char *fname) const; 33.77 + 33.78 + void update(long tm); 33.79 + void draw() const; 33.80 +}; 33.81 + 33.82 +#endif // PSYSPP_H_
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 34.2 +++ b/src/rtarg.cc Thu Nov 14 05:27:09 2013 +0200 34.3 @@ -0,0 +1,259 @@ 34.4 +#include <stack> 34.5 +#include "rtarg.h" 34.6 +#include "texture.h" 34.7 +#include "logger.h" 34.8 + 34.9 +RenderTarget::RenderTarget() 34.10 +{ 34.11 + width = height = 0; 34.12 + fbo = 0; 34.13 + rbuf_zstencil = 0; 34.14 + color_tex = 0; 34.15 + tex_face = 0; 34.16 + tex_targ = 0; 34.17 +} 34.18 + 34.19 +RenderTarget::~RenderTarget() 34.20 +{ 34.21 + cleanup(); 34.22 +} 34.23 + 34.24 +bool RenderTarget::create(unsigned int fmt) 34.25 +{ 34.26 + int vp[4]; 34.27 + glGetIntegerv(GL_VIEWPORT, vp); 34.28 + 34.29 + return create(vp[2] - vp[0], vp[3] - vp[1], fmt); 34.30 +} 34.31 + 34.32 +bool RenderTarget::create(int width, int height, unsigned int fmt) 34.33 +{ 34.34 + debug_log("RenderTarget::create(%d, %d)\n", width, height); 34.35 + cleanup(); 34.36 + 34.37 + tex_targ = GL_TEXTURE_2D; 34.38 + this->width = width; 34.39 + this->height = height; 34.40 + int tex_width = next_pow2(width); 34.41 + int tex_height = next_pow2(height); 34.42 + 34.43 + CHECKGLERR; 34.44 + color_tex = new Texture2D; 34.45 + color_tex->create(tex_width, tex_height, fmt); 34.46 + CHECKGLERR; 34.47 + tex_face = 0; 34.48 + 34.49 + glGenFramebuffers(1, &fbo); 34.50 + glBindFramebuffer(GL_FRAMEBUFFER, fbo); 34.51 + 34.52 + glBindTexture(GL_TEXTURE_2D, color_tex->get_id()); 34.53 + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color_tex->get_id(), 0); 34.54 + glBindTexture(GL_TEXTURE_2D, 0); 34.55 + 34.56 + glGenRenderbuffers(1, &rbuf_zstencil); 34.57 + glBindRenderbuffer(GL_RENDERBUFFER, rbuf_zstencil); 34.58 + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, tex_width, tex_height); 34.59 + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbuf_zstencil); 34.60 + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbuf_zstencil); 34.61 + 34.62 + glBindFramebuffer(GL_FRAMEBUFFER, 0); 34.63 + CHECKGLERR; 34.64 + return true; 34.65 +} 34.66 + 34.67 +bool RenderTarget::create(Texture *tex, int face) 34.68 +{ 34.69 + debug_log("RenderTarget::create(tex{%d, %d}, face:%d)\n", tex->get_size(0), 34.70 + tex->get_size(1), face); 34.71 + 34.72 + tex_targ = GL_TEXTURE_2D; 34.73 + if(dynamic_cast<TextureCube*>(tex)) { 34.74 + if(face >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) { 34.75 + tex_targ = face; 34.76 + } else if(face >= 0 && face < 6) { 34.77 + tex_targ = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face; 34.78 + } else { 34.79 + error_log("invalid face (%d) passed to RenderTarget::create(TextureCube*, int)\n", face); 34.80 + return false; 34.81 + } 34.82 + } 34.83 + 34.84 + cleanup(); 34.85 + 34.86 + width = tex->get_size(0); 34.87 + height = tex->get_size(1); 34.88 + 34.89 + color_tex = tex; 34.90 + 34.91 + glGenFramebuffers(1, &fbo); 34.92 + glBindFramebuffer(GL_FRAMEBUFFER, fbo); 34.93 + 34.94 + glBindTexture(tex_targ, color_tex->get_id()); 34.95 + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex_targ, color_tex->get_id(), 0); 34.96 + glBindTexture(tex_targ, 0); 34.97 + 34.98 + glGenRenderbuffers(1, &rbuf_zstencil); 34.99 + glBindRenderbuffer(GL_RENDERBUFFER, rbuf_zstencil); 34.100 + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); 34.101 + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbuf_zstencil); 34.102 + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbuf_zstencil); 34.103 + 34.104 + glBindFramebuffer(GL_FRAMEBUFFER, 0); 34.105 + CHECKGLERR; 34.106 + return true; 34.107 +} 34.108 + 34.109 +void RenderTarget::cleanup() 34.110 +{ 34.111 + delete color_tex; 34.112 + color_tex = 0; 34.113 + 34.114 + if(fbo) { 34.115 + glDeleteFramebuffers(1, &fbo); 34.116 + } 34.117 + if(rbuf_zstencil) { 34.118 + glDeleteRenderbuffers(1, &rbuf_zstencil); 34.119 + } 34.120 + 34.121 + fbo = rbuf_zstencil = 0; 34.122 + width = height = 0; 34.123 + tex_face = 0; 34.124 + tex_targ = 0; 34.125 +} 34.126 + 34.127 +bool RenderTarget::resize(int width, int height) 34.128 +{ 34.129 + this->width = width; 34.130 + this->height = height; 34.131 + int tex_width = next_pow2(width); 34.132 + int tex_height = next_pow2(height); 34.133 + 34.134 + debug_log("resizing render target (fbo %u): %dx%d [%dx%d]\n", fbo, width, height, tex_width, tex_height); 34.135 + 34.136 + glBindFramebuffer(GL_FRAMEBUFFER, fbo); 34.137 + 34.138 + color_tex->create(tex_width, tex_height, color_tex->get_format()); 34.139 + color_tex->bind(); 34.140 + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex_targ, color_tex->get_id(), 0); 34.141 + glBindTexture(tex_targ, 0); 34.142 + 34.143 + glBindRenderbuffer(GL_RENDERBUFFER, rbuf_zstencil); 34.144 + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, tex_width, tex_height); 34.145 + 34.146 + glBindFramebuffer(GL_FRAMEBUFFER, 0); 34.147 + return true; 34.148 +} 34.149 + 34.150 +int RenderTarget::get_width() const 34.151 +{ 34.152 + return width; 34.153 +} 34.154 + 34.155 +int RenderTarget::get_height() const 34.156 +{ 34.157 + return height; 34.158 +} 34.159 + 34.160 +Texture *RenderTarget::get_texture() const 34.161 +{ 34.162 + return color_tex; 34.163 +} 34.164 + 34.165 +Matrix4x4 RenderTarget::get_texture_matrix() const 34.166 +{ 34.167 + float sx = (float)width / (float)color_tex->get_size(0); 34.168 + float sy = (float)height / (float)color_tex->get_size(1); 34.169 + 34.170 + // counting on RVO to optimize this away 34.171 + return Matrix4x4(sx, 0, 0, 0, 34.172 + 0, sy, 0, 0, 34.173 + 0, 0, 1, 0, 34.174 + 0, 0, 0, 1); 34.175 +} 34.176 + 34.177 + 34.178 +static const char *fbstname[] = { 34.179 + "GL_FRAMEBUFFER_COMPLETE", 34.180 + "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT", 34.181 + "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT", 34.182 + "no such fbo error", 34.183 + "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS", 34.184 + "GL_FRAMEBUFFER_INCOMPLETE_FORMATS", 34.185 + "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER", 34.186 + "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER", 34.187 + "GL_FRAMEBUFFER_UNSUPPORTED" 34.188 +}; 34.189 + 34.190 +bool RenderTarget::check() const 34.191 +{ 34.192 + bool res = true; 34.193 + 34.194 +#ifndef GL_ES_VERSION_2_0 34.195 + int prev_fb = 0; 34.196 + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &prev_fb); 34.197 +#endif 34.198 + 34.199 + glBindFramebuffer(GL_FRAMEBUFFER, fbo); 34.200 + 34.201 + int status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 34.202 + if(status != GL_FRAMEBUFFER_COMPLETE) { 34.203 + error_log("RenderTarget::check: incomplete FBO %u: %s\n", fbo, 34.204 + fbstname[status - GL_FRAMEBUFFER_COMPLETE]); 34.205 + res = false; 34.206 + goto end; 34.207 + } 34.208 + 34.209 +end: 34.210 +#ifndef GL_ES_VERSION_2_0 34.211 + glBindFramebuffer(GL_FRAMEBUFFER, prev_fb); 34.212 +#endif 34.213 + return res; 34.214 +} 34.215 + 34.216 +void RenderTarget::bind() const 34.217 +{ 34.218 + glBindFramebuffer(GL_FRAMEBUFFER, fbo); 34.219 + 34.220 + glViewport(0, 0, width, height); 34.221 +} 34.222 + 34.223 +struct Viewport { int vp[4]; }; 34.224 +static std::stack<Viewport> vpstack; 34.225 + 34.226 +void set_render_target(const RenderTarget *rtarg) 34.227 +{ 34.228 + Viewport vp; 34.229 + 34.230 + if(rtarg) { 34.231 + glGetIntegerv(GL_VIEWPORT, vp.vp); 34.232 + vpstack.push(vp); 34.233 + 34.234 + rtarg->bind(); 34.235 + } else { 34.236 +#ifdef GL_ES_VERSION_2_0 34.237 + extern unsigned int default_fbo; 34.238 + glBindFramebuffer(GL_FRAMEBUFFER, default_fbo); 34.239 +#else 34.240 + glBindFramebuffer(GL_FRAMEBUFFER, 0); 34.241 +#endif 34.242 + 34.243 + if(vpstack.empty()) { 34.244 + return; 34.245 + } 34.246 + vp = vpstack.top(); 34.247 + vpstack.pop(); 34.248 + glViewport(vp.vp[0], vp.vp[1], vp.vp[2], vp.vp[3]); 34.249 + } 34.250 +} 34.251 + 34.252 +int next_pow2(int x) 34.253 +{ 34.254 + x--; 34.255 + x = (x >> 1) | x; 34.256 + x = (x >> 2) | x; 34.257 + x = (x >> 4) | x; 34.258 + x = (x >> 8) | x; 34.259 + x = (x >> 16) | x; 34.260 + return x + 1; 34.261 +} 34.262 +
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 35.2 +++ b/src/rtarg.h Thu Nov 14 05:27:09 2013 +0200 35.3 @@ -0,0 +1,49 @@ 35.4 +#ifndef RTARG_H_ 35.5 +#define RTARG_H_ 35.6 + 35.7 +#include "vmath/vmath.h" 35.8 +#include "opengl.h" 35.9 + 35.10 +class Texture; 35.11 + 35.12 +class RenderTarget { 35.13 +private: 35.14 + int width, height; 35.15 + 35.16 + unsigned int fbo; 35.17 + Texture *color_tex; 35.18 + unsigned int tex_targ; 35.19 + int tex_face; 35.20 + unsigned int rbuf_zstencil; 35.21 + 35.22 +public: 35.23 + RenderTarget(); 35.24 + ~RenderTarget(); 35.25 + 35.26 + bool create(unsigned int fmt = GL_RGBA); 35.27 + bool create(int width, int height, unsigned int fmt = GL_RGBA); 35.28 + bool create(Texture *tex, int face = 0); 35.29 + 35.30 + void cleanup(); 35.31 + 35.32 + bool resize(int width, int height); 35.33 + 35.34 + int get_width() const; 35.35 + int get_height() const; 35.36 + 35.37 + Texture *get_texture() const; 35.38 + 35.39 + /** calculates a texture matrix to map the full texture space 35.40 + * onto the part of the texture occupied by the render target 35.41 + */ 35.42 + Matrix4x4 get_texture_matrix() const; 35.43 + 35.44 + bool check() const; 35.45 + void bind() const; 35.46 +}; 35.47 + 35.48 +void set_render_target(const RenderTarget *rtarg); 35.49 + 35.50 +int next_pow2(int x); 35.51 + 35.52 +#endif // RTARG_H_
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 36.2 +++ b/src/scene.cc Thu Nov 14 05:27:09 2013 +0200 36.3 @@ -0,0 +1,39 @@ 36.4 +#include "scene.h" 36.5 +#include "opengl.h" 36.6 + 36.7 +Scene::~Scene() 36.8 +{ 36.9 + destroy(); 36.10 +} 36.11 + 36.12 +void Scene::destroy() 36.13 +{ 36.14 + for(size_t i=0; i<objects.size(); i++) { 36.15 + delete objects[i]; 36.16 + } 36.17 + objects.clear(); 36.18 + 36.19 + for(size_t i=0; i<meshes.size(); i++) { 36.20 + delete meshes[i]; 36.21 + } 36.22 + meshes.clear(); 36.23 + 36.24 + for(size_t i=0; i<curves.size(); i++) { 36.25 + delete curves[i]; 36.26 + } 36.27 + curves.clear(); 36.28 +} 36.29 + 36.30 +void Scene::draw(long msec) const 36.31 +{ 36.32 + for(size_t i=0; i<objects.size(); i++) { 36.33 + objects[i]->draw(msec); 36.34 + } 36.35 + 36.36 + if(objects.empty()) { 36.37 + printf("rendering meshes directly\n"); 36.38 + for(size_t i=0; i<meshes.size(); i++) { 36.39 + meshes[i]->draw(); 36.40 + } 36.41 + } 36.42 +}
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 37.2 +++ b/src/scene.h Thu Nov 14 05:27:09 2013 +0200 37.3 @@ -0,0 +1,20 @@ 37.4 +#ifndef SCENE_H_ 37.5 +#define SCENE_H_ 37.6 + 37.7 +#include <vector> 37.8 +#include "object.h" 37.9 +#include "curve.h" 37.10 + 37.11 +class Scene { 37.12 +public: 37.13 + std::vector<Object*> objects; 37.14 + std::vector<Mesh*> meshes; 37.15 + std::vector<Curve*> curves; 37.16 + 37.17 + ~Scene(); 37.18 + void destroy(); 37.19 + 37.20 + void draw(long msec = 0) const; 37.21 +}; 37.22 + 37.23 +#endif // SCENE_H_
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 38.2 +++ b/src/sdrman.cc Thu Nov 14 05:27:09 2013 +0200 38.3 @@ -0,0 +1,27 @@ 38.4 +#include "sdrman.h" 38.5 + 38.6 +ShaderSet vsdrset(GL_VERTEX_SHADER); 38.7 +ShaderSet psdrset(GL_FRAGMENT_SHADER); 38.8 + 38.9 +ShaderProg *get_sdrprog(const char *vname, const char *pname) 38.10 +{ 38.11 + Shader *vsdr = vname ? vsdrset.get(vname) : 0; 38.12 + Shader *psdr = pname ? psdrset.get(pname) : 0; 38.13 + 38.14 + if(vname && !vsdr) { 38.15 + return 0; 38.16 + } 38.17 + if(pname && !psdr) { 38.18 + return 0; 38.19 + } 38.20 + if(!vsdr && !psdr) { 38.21 + return 0; 38.22 + } 38.23 + 38.24 + ShaderProg *prog = new ShaderProg; 38.25 + if(!prog->create(vsdr, psdr)) { 38.26 + delete prog; 38.27 + return 0; 38.28 + } 38.29 + return prog; 38.30 +}
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 39.2 +++ b/src/sdrman.h Thu Nov 14 05:27:09 2013 +0200 39.3 @@ -0,0 +1,11 @@ 39.4 +#ifndef SDRMAN_H_ 39.5 +#define SDRMAN_H_ 39.6 + 39.7 +#include "shader.h" 39.8 + 39.9 +extern ShaderSet vsdrset; 39.10 +extern ShaderSet psdrset; 39.11 + 39.12 +ShaderProg *get_sdrprog(const char *vname, const char *pname); 39.13 + 39.14 +#endif // SDRMAN_H_
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 40.2 +++ b/src/shader.cc Thu Nov 14 05:27:09 2013 +0200 40.3 @@ -0,0 +1,641 @@ 40.4 +#include <stdio.h> 40.5 +#include <string.h> 40.6 +#include <stdarg.h> 40.7 +#include <errno.h> 40.8 +#include "opengl.h" 40.9 +#include "shader.h" 40.10 +#include "logger.h" 40.11 +#include "unistate.h" 40.12 +#include "mesh.h" 40.13 + 40.14 +#ifdef _MSC_VER 40.15 +#include <malloc.h> 40.16 +#else 40.17 +#include <alloca.h> 40.18 +#endif 40.19 + 40.20 +#ifdef __GLEW_H__ 40.21 +#define HAVE_GEOMETRY_SHADER 40.22 +#define HAVE_TESSELATION_SHADER 40.23 +#endif 40.24 + 40.25 +static void bind_standard_attr(const ShaderProg *prog); 40.26 +static const char *strtype(unsigned int type); 40.27 + 40.28 +ShaderProg *ShaderProg::current; 40.29 + 40.30 +Shader::Shader() 40.31 +{ 40.32 + sdr = type = 0; 40.33 + name = 0; 40.34 +} 40.35 + 40.36 +Shader::~Shader() 40.37 +{ 40.38 + destroy(); 40.39 +} 40.40 + 40.41 +unsigned int Shader::get_id() const 40.42 +{ 40.43 + return sdr; 40.44 +} 40.45 + 40.46 +void Shader::set_name(const char *name) 40.47 +{ 40.48 + delete [] this->name; 40.49 + this->name = new char[strlen(name) + 1]; 40.50 + strcpy(this->name, name); 40.51 +} 40.52 + 40.53 +const char *Shader::get_name() const 40.54 +{ 40.55 + return name; 40.56 +} 40.57 + 40.58 +bool Shader::create(const char *src, unsigned int type) 40.59 +{ 40.60 +#if !GL_ES_VERSION_2_0 40.61 + const char *src_arr[] = {src}; 40.62 +#else 40.63 + const char *src_arr[] = { "precision mediump float; ", src }; 40.64 +#endif 40.65 + 40.66 + if(!sdr) { 40.67 + sdr = glCreateShader(type); 40.68 + } 40.69 + 40.70 + info_log("compiling shader: %s... ", name ? name : ""); 40.71 + 40.72 + glShaderSource(sdr, sizeof src_arr / sizeof *src_arr, src_arr, 0); 40.73 + glCompileShader(sdr); 40.74 + 40.75 + int status; 40.76 + glGetShaderiv(sdr, GL_COMPILE_STATUS, &status); 40.77 + 40.78 + info_log(status ? "success\n" : "failed\n"); 40.79 + 40.80 + int info_len; 40.81 + glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len); 40.82 + if(info_len > 1) { 40.83 + char *buf = (char*)alloca(info_len); 40.84 + glGetShaderInfoLog(sdr, info_len, 0, buf); 40.85 + buf[info_len - 1] = 0; 40.86 + 40.87 + if(status) { 40.88 + info_log("%s\n", buf); 40.89 + } else { 40.90 + error_log("%s\n", buf); 40.91 + } 40.92 + } 40.93 + 40.94 + return status == GL_TRUE; 40.95 +} 40.96 + 40.97 +void Shader::destroy() 40.98 +{ 40.99 + if(sdr) { 40.100 + glDeleteShader(sdr); 40.101 + } 40.102 + sdr = type = 0; 40.103 + 40.104 + delete [] name; 40.105 + name = 0; 40.106 +} 40.107 + 40.108 +bool Shader::load(const char *fname, unsigned int type) 40.109 +{ 40.110 + FILE *fp; 40.111 + 40.112 + if(!(fp = fopen(fname, "rb"))) { 40.113 + error_log("failed to load %s shader: %s: %s\n", strtype(type), fname, strerror(errno)); 40.114 + return false; 40.115 + } 40.116 + 40.117 + fseek(fp, 0, SEEK_END); 40.118 + long sz = ftell(fp); 40.119 + rewind(fp); 40.120 + 40.121 + char *src = (char*)alloca(sz + 1); 40.122 + if(fread(src, 1, sz, fp) < (size_t)sz) { 40.123 + error_log("failed to load %s shader: %s: %s\n", strtype(type), fname, strerror(errno)); 40.124 + fclose(fp); 40.125 + return false; 40.126 + } 40.127 + src[sz] = 0; 40.128 + fclose(fp); 40.129 + 40.130 + set_name(fname); 40.131 + return create(src, type); 40.132 +} 40.133 + 40.134 +// ---- shader program ---- 40.135 +ShaderProg::ShaderProg() 40.136 +{ 40.137 + prog = 0; 40.138 + must_link = true; 40.139 +} 40.140 + 40.141 +ShaderProg::~ShaderProg() 40.142 +{ 40.143 + destroy(); 40.144 +} 40.145 + 40.146 +unsigned int ShaderProg::get_id() const 40.147 +{ 40.148 + return prog; 40.149 +} 40.150 + 40.151 +bool ShaderProg::create(const char *src, unsigned int type, ...) 40.152 +{ 40.153 + va_list ap; 40.154 + 40.155 + va_start(ap, type); 40.156 + bool res = create(src, type, ap); 40.157 + va_end(ap); 40.158 + 40.159 + return res; 40.160 +} 40.161 + 40.162 +bool ShaderProg::create(const char *src, unsigned int type, va_list ap) 40.163 +{ 40.164 + destroy(); 40.165 + prog = glCreateProgram(); 40.166 + 40.167 + while(src) { 40.168 + Shader *sdr = new Shader; 40.169 + if(!sdr->create(src, type)) { 40.170 + va_end(ap); 40.171 + return false; 40.172 + } 40.173 + add_shader(sdr); 40.174 + src = va_arg(ap, const char*); 40.175 + type = va_arg(ap, unsigned int); 40.176 + } 40.177 + return link(); 40.178 +} 40.179 + 40.180 +bool ShaderProg::create(const char *vsrc, const char *psrc) 40.181 +{ 40.182 + return create(VSDR(vsrc), PSDR(psrc), 0); 40.183 +} 40.184 + 40.185 +bool ShaderProg::create(Shader *sdr, ...) 40.186 +{ 40.187 + va_list ap; 40.188 + 40.189 + va_start(ap, sdr); 40.190 + bool res = create(sdr, ap); 40.191 + va_end(ap); 40.192 + 40.193 + return res; 40.194 +} 40.195 + 40.196 +bool ShaderProg::create(Shader *sdr, va_list ap) 40.197 +{ 40.198 + destroy(); 40.199 + prog = glCreateProgram(); 40.200 + 40.201 + while(sdr) { 40.202 + add_shader(sdr); 40.203 + sdr = va_arg(ap, Shader*); 40.204 + } 40.205 + return link(); 40.206 +} 40.207 + 40.208 +bool ShaderProg::create(Shader *vsdr, Shader *psdr) 40.209 +{ 40.210 + return create(vsdr, psdr, 0); 40.211 +} 40.212 + 40.213 +void ShaderProg::destroy() 40.214 +{ 40.215 + if(prog) { 40.216 + glDeleteProgram(prog); 40.217 + } 40.218 + prog = 0; 40.219 + 40.220 + shaders.clear(); 40.221 + // don't actually destroy the shaders, let the ShaderSet own them 40.222 +} 40.223 + 40.224 +bool ShaderProg::load(const char *fname, unsigned int type, ...) 40.225 +{ 40.226 + va_list ap; 40.227 + va_start(ap, type); 40.228 + bool res = load(fname, type, ap); 40.229 + va_end(ap); 40.230 + 40.231 + return res; 40.232 +} 40.233 + 40.234 +bool ShaderProg::load(const char *fname, unsigned int type, va_list ap) 40.235 +{ 40.236 + destroy(); 40.237 + prog = glCreateProgram(); 40.238 + 40.239 + while(fname) { 40.240 + Shader *sdr = new Shader; 40.241 + if(!sdr->load(fname, type)) { 40.242 + delete sdr; 40.243 + return false; 40.244 + } 40.245 + add_shader(sdr); 40.246 + 40.247 + if((fname = va_arg(ap, const char*))) { 40.248 + type = va_arg(ap, unsigned int); 40.249 + } 40.250 + } 40.251 + 40.252 + return link(); 40.253 +} 40.254 + 40.255 +bool ShaderProg::load(const char *vfname, const char *pfname) 40.256 +{ 40.257 + return load(VSDR(vfname), PSDR(pfname), 0); 40.258 +} 40.259 + 40.260 +void ShaderProg::add_shader(Shader *sdr) 40.261 +{ 40.262 + glAttachShader(prog, sdr->get_id()); 40.263 +} 40.264 + 40.265 +bool ShaderProg::link() const 40.266 +{ 40.267 + bind_standard_attr(this); 40.268 + 40.269 + CHECKGLERR; 40.270 + info_log("linking program ... "); 40.271 + glLinkProgram(prog); 40.272 + 40.273 + int status; 40.274 + glGetProgramiv(prog, GL_LINK_STATUS, &status); 40.275 + 40.276 + info_log(status ? "success\n" : "failed\n"); 40.277 + 40.278 + int info_len; 40.279 + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len); 40.280 + if(info_len > 1) { 40.281 + char *buf = (char*)alloca(info_len); 40.282 + glGetProgramInfoLog(prog, info_len, 0, buf); 40.283 + buf[info_len - 1] = 0; 40.284 + 40.285 + if(status) { 40.286 + info_log("%s\n", buf); 40.287 + } else { 40.288 + error_log("%s\n", buf); 40.289 + } 40.290 + } 40.291 + 40.292 + if(status) { 40.293 + must_link = false; 40.294 + cache_state_uniforms(); 40.295 + 40.296 + return true; 40.297 + } 40.298 + return false; 40.299 +} 40.300 + 40.301 +void ShaderProg::bind() const 40.302 +{ 40.303 + CHECKGLERR; 40.304 + if(must_link) { 40.305 + if(!link()) { 40.306 + return; 40.307 + } 40.308 + } 40.309 + CHECKGLERR; 40.310 + glUseProgram(prog); 40.311 + ShaderProg::current = (ShaderProg*)this; 40.312 + 40.313 + setup_state_uniforms(); 40.314 +} 40.315 + 40.316 + 40.317 +int ShaderProg::get_attrib_location(const char *name) const 40.318 +{ 40.319 + glUseProgram(prog); 40.320 + return glGetAttribLocation(prog, name); 40.321 +} 40.322 + 40.323 +void ShaderProg::set_attrib_location(const char *name, int loc) const 40.324 +{ 40.325 + glBindAttribLocation(prog, loc, name); 40.326 + must_link = true; 40.327 +} 40.328 + 40.329 +int ShaderProg::get_uniform_location(const char *name) const 40.330 +{ 40.331 + glUseProgram(prog); 40.332 + return glGetUniformLocation(prog, name); 40.333 +} 40.334 + 40.335 +bool ShaderProg::set_uniform(int loc, int val) const 40.336 +{ 40.337 + glUseProgram(prog); 40.338 + if(loc >= 0) { 40.339 + glUniform1i(loc, val); 40.340 + return true; 40.341 + } 40.342 + return false; 40.343 +} 40.344 + 40.345 +bool ShaderProg::set_uniform(int loc, float val) const 40.346 +{ 40.347 + glUseProgram(prog); 40.348 + if(loc >= 0) { 40.349 + glUniform1f(loc, val); 40.350 + return true; 40.351 + } 40.352 + return false; 40.353 +} 40.354 + 40.355 +bool ShaderProg::set_uniform(int loc, const Vector2 &v) const 40.356 +{ 40.357 + glUseProgram(prog); 40.358 + if(loc >= 0) { 40.359 + glUniform2f(loc, v.x, v.y); 40.360 + return true; 40.361 + } 40.362 + return false; 40.363 +} 40.364 + 40.365 +bool ShaderProg::set_uniform(int loc, const Vector3 &v) const 40.366 +{ 40.367 + glUseProgram(prog); 40.368 + if(loc >= 0) { 40.369 + glUniform3f(loc, v.x, v.y, v.z); 40.370 + return true; 40.371 + } 40.372 + return false; 40.373 +} 40.374 + 40.375 +bool ShaderProg::set_uniform(int loc, const Vector4 &v) const 40.376 +{ 40.377 + glUseProgram(prog); 40.378 + if(loc >= 0) { 40.379 + glUniform4f(loc, v.x, v.y, v.z, v.w); 40.380 + return true; 40.381 + } 40.382 + return false; 40.383 +} 40.384 + 40.385 +bool ShaderProg::set_uniform(int loc, const Matrix3x3 &m) const 40.386 +{ 40.387 + glUseProgram(prog); 40.388 + if(loc >= 0) { 40.389 + glUniformMatrix3fv(loc, 1, GL_TRUE, m[0]); 40.390 + return true; 40.391 + } 40.392 + return false; 40.393 +} 40.394 + 40.395 +bool ShaderProg::set_uniform(int loc, const Matrix4x4 &m) const 40.396 +{ 40.397 + glUseProgram(prog); 40.398 + if(loc >= 0) { 40.399 + glUniformMatrix4fv(loc, 1, GL_TRUE, m[0]); 40.400 + return true; 40.401 + } 40.402 + return false; 40.403 +} 40.404 + 40.405 + 40.406 +bool ShaderProg::set_uniform(const char *name, int val) const 40.407 +{ 40.408 + return set_uniform(get_uniform_location(name), val); 40.409 +} 40.410 + 40.411 +bool ShaderProg::set_uniform(const char *name, float val) const 40.412 +{ 40.413 + return set_uniform(get_uniform_location(name), val); 40.414 +} 40.415 + 40.416 +bool ShaderProg::set_uniform(const char *name, const Vector2 &v) const 40.417 +{ 40.418 + return set_uniform(get_uniform_location(name), v); 40.419 +} 40.420 + 40.421 +bool ShaderProg::set_uniform(const char *name, const Vector3 &v) const 40.422 +{ 40.423 + return set_uniform(get_uniform_location(name), v); 40.424 +} 40.425 + 40.426 +bool ShaderProg::set_uniform(const char *name, const Vector4 &v) const 40.427 +{ 40.428 + return set_uniform(get_uniform_location(name), v); 40.429 +} 40.430 + 40.431 +bool ShaderProg::set_uniform(const char *name, const Matrix3x3 &m) const 40.432 +{ 40.433 + return set_uniform(get_uniform_location(name), m); 40.434 +} 40.435 + 40.436 +bool ShaderProg::set_uniform(const char *name, const Matrix4x4 &m) const 40.437 +{ 40.438 + return set_uniform(get_uniform_location(name), m); 40.439 +} 40.440 + 40.441 +static StType unist_type(GLenum type) 40.442 +{ 40.443 + switch(type) { 40.444 + case GL_FLOAT: 40.445 + return ST_FLOAT; 40.446 + case GL_FLOAT_VEC2: 40.447 + return ST_FLOAT2; 40.448 + case GL_FLOAT_VEC3: 40.449 + return ST_FLOAT3; 40.450 + case GL_FLOAT_VEC4: 40.451 + return ST_FLOAT4; 40.452 + case GL_INT: 40.453 + case GL_SAMPLER_2D: 40.454 + case GL_SAMPLER_CUBE: 40.455 +#if !GL_ES_VERSION_2_0 40.456 + case GL_SAMPLER_1D: 40.457 + case GL_SAMPLER_3D: 40.458 + case GL_SAMPLER_1D_SHADOW: 40.459 + case GL_SAMPLER_2D_SHADOW: 40.460 +#endif 40.461 + return ST_INT; 40.462 + case GL_INT_VEC2: 40.463 + return ST_INT2; 40.464 + case GL_INT_VEC3: 40.465 + return ST_INT3; 40.466 + case GL_INT_VEC4: 40.467 + return ST_INT4; 40.468 + case GL_FLOAT_MAT3: 40.469 + return ST_MATRIX3; 40.470 + case GL_FLOAT_MAT4: 40.471 + return ST_MATRIX4; 40.472 + default: 40.473 + break; 40.474 + } 40.475 + return ST_UNKNOWN; 40.476 +} 40.477 + 40.478 +void ShaderProg::cache_state_uniforms() const 40.479 +{ 40.480 + if(!glIsProgram(prog)) { 40.481 + return; 40.482 + } 40.483 + 40.484 + int num_uni; 40.485 + glGetProgramiv(prog, GL_ACTIVE_UNIFORMS, &num_uni); 40.486 + 40.487 + char name[256]; 40.488 + for(int i=0; i<num_uni; i++) { 40.489 + GLint sz; 40.490 + GLenum type; 40.491 + glGetActiveUniform(prog, i, sizeof name - 1, 0, &sz, &type, name); 40.492 + 40.493 + if(strstr(name, "st_") == name) { 40.494 + StateLocCache s; 40.495 + s.sidx = add_unistate(name, unist_type(type)); 40.496 + s.loc = glGetUniformLocation(prog, name); 40.497 + stloc_cache.push_back(s); 40.498 + } 40.499 + } 40.500 +} 40.501 + 40.502 +void ShaderProg::setup_state_uniforms() const 40.503 +{ 40.504 + for(size_t i=0; i<stloc_cache.size(); i++) { 40.505 + setup_unistate(stloc_cache[i].sidx, this, stloc_cache[i].loc); 40.506 + CHECKGLERR; 40.507 + } 40.508 +} 40.509 + 40.510 +// ---- ShaderSet ---- 40.511 +static Shader *load_shader(const char *fname, unsigned int type) 40.512 +{ 40.513 + Shader *sdr = new Shader; 40.514 + if(!sdr->load(fname, type)) { 40.515 + delete sdr; 40.516 + return 0; 40.517 + } 40.518 + return sdr; 40.519 +} 40.520 + 40.521 +static Shader *load_vertex_shader(const char *fname) 40.522 +{ 40.523 + return load_shader(fname, GL_VERTEX_SHADER); 40.524 +} 40.525 + 40.526 +static Shader *load_pixel_shader(const char *fname) 40.527 +{ 40.528 + return load_shader(fname, GL_FRAGMENT_SHADER); 40.529 +} 40.530 + 40.531 +#ifdef HAVE_GEOMETRY_SHADER 40.532 +static Shader *load_geom_shader(const char *fname) 40.533 +{ 40.534 + return load_shader(fname, GL_GEOMETRY_SHADER); 40.535 +} 40.536 +#endif 40.537 + 40.538 +#ifdef HAVE_TESSELATION_SHADER 40.539 +static Shader *load_tc_shader(const char *fname) 40.540 +{ 40.541 + return load_shader(fname, GL_TESS_CONTROL_SHADER); 40.542 +} 40.543 + 40.544 +static Shader *load_te_shader(const char *fname) 40.545 +{ 40.546 + return load_shader(fname, GL_TESS_EVALUATION_SHADER); 40.547 +} 40.548 +#endif 40.549 + 40.550 +static void destroy_shader(Shader *sdr) 40.551 +{ 40.552 + delete sdr; 40.553 +} 40.554 + 40.555 +ShaderSet::ShaderSet(unsigned int type) 40.556 + : DataSet<Shader*>(0, destroy_shader) 40.557 +{ 40.558 + this->type = type; 40.559 + 40.560 + switch(type) { 40.561 + case GL_VERTEX_SHADER: 40.562 + load = load_vertex_shader; 40.563 + break; 40.564 + 40.565 + case GL_FRAGMENT_SHADER: 40.566 + load = load_pixel_shader; 40.567 + break; 40.568 + 40.569 +#ifdef HAVE_GEOMETRY_SHADER 40.570 + case GL_GEOMETRY_SHADER: 40.571 + load = load_geom_shader; 40.572 + break; 40.573 +#endif 40.574 + 40.575 +#ifdef HAVE_TESSELATION_SHADER 40.576 + case GL_TESS_CONTROL_SHADER: 40.577 + load = load_tc_shader; 40.578 + break; 40.579 + 40.580 + case GL_TESS_EVALUATION_SHADER: 40.581 + load = load_te_shader; 40.582 + break; 40.583 +#endif 40.584 + 40.585 + default: 40.586 + error_log("ShaderSet constructed with invalid shader type!\n"); 40.587 + } 40.588 +} 40.589 + 40.590 +static struct { const char *name; int loc; } attr_loc[] = { 40.591 + {"attr_vertex", MESH_ATTR_VERTEX}, 40.592 + {"attr_normal", MESH_ATTR_NORMAL}, 40.593 + {"attr_tangent", MESH_ATTR_TANGENT}, 40.594 + {"attr_texcoord", MESH_ATTR_TEXCOORD}, 40.595 + {"attr_color", MESH_ATTR_COLOR}, 40.596 + {"attr_boneweights", MESH_ATTR_BONEWEIGHTS}, 40.597 + {"attr_boneidx", MESH_ATTR_BONEIDX} 40.598 +}; 40.599 + 40.600 +static void bind_standard_attr(const ShaderProg *prog) 40.601 +{ 40.602 + // we must link once to find out which are the active attributes 40.603 + glLinkProgram(prog->get_id()); 40.604 + 40.605 + int num_attr; 40.606 + glGetProgramiv(prog->get_id(), GL_ACTIVE_ATTRIBUTES, &num_attr); 40.607 + 40.608 + char name[256]; 40.609 + for(int i=0; i<num_attr; i++) { 40.610 + GLint sz; 40.611 + GLenum type; 40.612 + glGetActiveAttrib(prog->get_id(), i, sizeof name - 1, 0, &sz, &type, name); 40.613 + 40.614 + for(int j=0; j<sizeof attr_loc / sizeof *attr_loc; j++) { 40.615 + if(strcmp(name, attr_loc[j].name) == 0) { 40.616 + prog->set_attrib_location(name, attr_loc[j].loc); 40.617 + } 40.618 + } 40.619 + } 40.620 +} 40.621 + 40.622 + 40.623 +static const char *strtype(unsigned int type) 40.624 +{ 40.625 + switch(type) { 40.626 + case GL_VERTEX_SHADER: 40.627 + return "vertex"; 40.628 + case GL_FRAGMENT_SHADER: 40.629 + return "fragment"; 40.630 +#ifdef HAVE_GEOMETRY_SHADER 40.631 + case GL_GEOMETRY_SHADER: 40.632 + return "geometry"; 40.633 +#endif 40.634 +#ifdef HAVE_TESSELATION_SHADER 40.635 + case GL_TESS_CONTROL_SHADER: 40.636 + return "tesselation control"; 40.637 + case GL_TESS_EVALUATION_SHADER: 40.638 + return "tesselation evaluation"; 40.639 +#endif 40.640 + default: 40.641 + break; 40.642 + } 40.643 + return "<unknown>"; 40.644 +}
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 41.2 +++ b/src/shader.h Thu Nov 14 05:27:09 2013 +0200 41.3 @@ -0,0 +1,135 @@ 41.4 +#ifndef SHADER_H_ 41.5 +#define SHADER_H_ 41.6 + 41.7 +#include <vector> 41.8 +#include "vmath/vmath.h" 41.9 +#include "opengl.h" 41.10 +#include "dataset.h" 41.11 + 41.12 +class Shader { 41.13 +private: 41.14 + unsigned int sdr; 41.15 + unsigned int type; 41.16 + char *name; 41.17 + 41.18 +public: 41.19 + Shader(); 41.20 + ~Shader(); 41.21 + 41.22 + unsigned int get_id() const; 41.23 + 41.24 + void set_name(const char *name); 41.25 + const char *get_name() const; 41.26 + 41.27 + bool create(const char *src, unsigned int type); 41.28 + void destroy(); 41.29 + 41.30 + bool load(const char *fname, unsigned int type); 41.31 +}; 41.32 + 41.33 +#define VSDR(s) s, GL_VERTEX_SHADER 41.34 +#define FSDR(s) s, GL_FRAGMENT_SHADER 41.35 +#define PSDR(s) FSDR(s) 41.36 +#define GSDR(s) s, GL_GEOMETRY_SHADER 41.37 +#define TCSDR(s) s, GL_TESS_CONTROL_SHADER 41.38 +#define TESDR(s) s, GL_TESS_EVALUATION_SHADER 41.39 + 41.40 +class ShaderProg { 41.41 +private: 41.42 + unsigned int prog; 41.43 + mutable bool must_link; 41.44 + std::vector<Shader*> shaders; 41.45 + 41.46 + struct StateLocCache { int sidx, loc; }; 41.47 + /** a cache of all st_ prefixed uniform locations and their corresponding 41.48 + * index in the global uniform state vector (see unistate.h) 41.49 + */ 41.50 + mutable std::vector<StateLocCache> stloc_cache; 41.51 + 41.52 + void cache_state_uniforms() const; 41.53 + void setup_state_uniforms() const; 41.54 + 41.55 +public: 41.56 + static ShaderProg *current; 41.57 + 41.58 + ShaderProg(); 41.59 + ~ShaderProg(); 41.60 + 41.61 + /// returns the OpenGL object id for this shader program 41.62 + unsigned int get_id() const; 41.63 + 41.64 + /** takes a series of shaders, and constructs a program object by linking 41.65 + * them together. Terminate with a null pointer (don't use 0!) */ 41.66 + bool create(Shader *sdr, ...); 41.67 + /// same as above, but with a va_list instead of variable arguments. 41.68 + bool create(Shader *sdr, va_list ap); 41.69 + /** takes two shaders (vertex and pixel) and constructs a program object by 41.70 + * linking them together. Either one can be null. */ 41.71 + bool create(Shader *vsdr, Shader *psdr); 41.72 + 41.73 + /** takes a series of shader source/shader type pairs and constructs a program 41.74 + * object by linking them together. Terminate with a null pointer (don't use 0!) 41.75 + * You can use the VSDR, PSDR, GSDR, TCSDR, TESDR convenience macros for passing 41.76 + * the pairs. 41.77 + * Example: create(VSDR(vsrc0), VSDR(vsrc1), PSDR(psrc), NULL); 41.78 + */ 41.79 + bool create(const char *src, unsigned int type, ...); 41.80 + /// same as above, but with a va_list instead of variable arguments. 41.81 + bool create(const char *src, unsigned int type, va_list ap); 41.82 + /** takes two shaders source strings (vertex and pixel) and constructs 41.83 + * a program object by linking them together. Either one can be null. */ 41.84 + bool create(const char *vsrc, const char *psrc); 41.85 + 41.86 + void destroy(); 41.87 + 41.88 + /** takes a series of shader filename/shader type pairs, loads the shaders and 41.89 + * constructs a program object by linking them together. Terminate with a null 41.90 + * pointer (don't use 0!). You can use the VSDR, PSDR, GSDR, TCSDR, TESDR convenience 41.91 + * macros for passing the pairs. 41.92 + * Example: load(VSDR("vsdr1.glsl"), VSDR("vsdr2.glsl"), PSDR("pixel.glsl"), NULL); 41.93 + */ 41.94 + bool load(const char *fname, unsigned int type, ...); 41.95 + /// same as above, but with a va_list instead of variable arguments. 41.96 + bool load(const char *fname, unsigned int type, va_list ap); 41.97 + /** takes the filenames of two shader files (vertex and pixel), loads them and 41.98 + * constructs a program object by linking them together. Either one can be null */ 41.99 + bool load(const char *vsrc, const char *psrc); 41.100 + 41.101 + void add_shader(Shader *sdr); 41.102 + bool link() const; 41.103 + 41.104 + void bind() const; 41.105 + 41.106 + int get_attrib_location(const char *name) const; 41.107 + void set_attrib_location(const char *name, int loc) const; 41.108 + 41.109 + int get_uniform_location(const char *name) const; 41.110 + 41.111 + bool set_uniform(int loc, int val) const; 41.112 + bool set_uniform(int loc, float val) const; 41.113 + bool set_uniform(int loc, const Vector2 &v) const; 41.114 + bool set_uniform(int loc, const Vector3 &v) const; 41.115 + bool set_uniform(int loc, const Vector4 &v) const; 41.116 + bool set_uniform(int loc, const Matrix3x3 &m) const; 41.117 + bool set_uniform(int loc, const Matrix4x4 &m) const; 41.118 + 41.119 + bool set_uniform(const char *name, int val) const; 41.120 + bool set_uniform(const char *name, float val) const; 41.121 + bool set_uniform(const char *name, const Vector2 &v) const; 41.122 + bool set_uniform(const char *name, const Vector3 &v) const; 41.123 + bool set_uniform(const char *name, const Vector4 &v) const; 41.124 + bool set_uniform(const char *name, const Matrix3x3 &m) const; 41.125 + bool set_uniform(const char *name, const Matrix4x4 &m) const; 41.126 + 41.127 + friend void setup_unistate(const ShaderProg*); 41.128 +}; 41.129 + 41.130 +class ShaderSet : public DataSet<Shader*> { 41.131 +private: 41.132 + unsigned int type; 41.133 + 41.134 +public: 41.135 + ShaderSet(unsigned int type); 41.136 +}; 41.137 + 41.138 +#endif // SHADER_H_
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 42.2 +++ b/src/texgen.cc Thu Nov 14 05:27:09 2013 +0200 42.3 @@ -0,0 +1,137 @@ 42.4 +#include "texgen.h" 42.5 + 42.6 +static void intcolor(const Vector4 &color, int *icol); 42.7 + 42.8 +Image *texgen_solid(int xsz, int ysz, const Vector4 &color) 42.9 +{ 42.10 + Image *img = new Image; 42.11 + if(!img->create(xsz, ysz, Image::FMT_RGBA)) { 42.12 + delete img; 42.13 + return 0; 42.14 + } 42.15 + 42.16 + int col[4]; 42.17 + intcolor(color, col); 42.18 + 42.19 + unsigned char *pix = (unsigned char*)img->get_pixels(); 42.20 + for(int i=0; i<xsz * ysz; i++) { 42.21 + *pix++ = col[0]; 42.22 + *pix++ = col[1]; 42.23 + *pix++ = col[2]; 42.24 + *pix++ = col[3]; 42.25 + } 42.26 + return img; 42.27 +} 42.28 + 42.29 +Image *texgen_chess(int xsz, int ysz, int usub, int vsub, const Vector4 &col1, const Vector4 &col2) 42.30 +{ 42.31 + Image *img = new Image; 42.32 + if(!img->create(xsz, ysz, Image::FMT_RGBA)) { 42.33 + delete img; 42.34 + return 0; 42.35 + } 42.36 + 42.37 + int c1[4], c2[4]; 42.38 + intcolor(col1, c1); 42.39 + intcolor(col2, c2); 42.40 + 42.41 + int udiv = xsz / usub; 42.42 + int vdiv = ysz / vsub; 42.43 + 42.44 + unsigned char *pix = (unsigned char*)img->get_pixels(); 42.45 + for(int i=0; i<ysz; i++) { 42.46 + for(int j=0; j<xsz; j++) { 42.47 + if(((i / vdiv) & 1) == ((j / udiv) & 1)) { 42.48 + *pix++ = c1[0]; 42.49 + *pix++ = c1[1]; 42.50 + *pix++ = c1[2]; 42.51 + *pix++ = c1[3]; 42.52 + } else { 42.53 + *pix++ = c2[0]; 42.54 + *pix++ = c2[1]; 42.55 + *pix++ = c2[2]; 42.56 + *pix++ = c2[3]; 42.57 + } 42.58 + } 42.59 + } 42.60 + return img; 42.61 +} 42.62 + 42.63 + 42.64 +Image *texgen(int xsz, int ysz, float usize, float vsize, Vector4 (*eval)(float, float, void*), void *cls) 42.65 +{ 42.66 + Image *img = new Image; 42.67 + if(!img->create(xsz, ysz, Image::FMT_RGBA)) { 42.68 + delete img; 42.69 + return 0; 42.70 + } 42.71 + 42.72 + unsigned char *pix = (unsigned char*)img->get_pixels(); 42.73 + for(int i=0; i<ysz; i++) { 42.74 + for(int j=0; j<xsz; j++) { 42.75 + float x = usize * (float)j / (float)xsz; 42.76 + float y = vsize * (float)i / (float)ysz; 42.77 + 42.78 + Vector4 color = eval(x, y, cls); 42.79 + 42.80 + int icol[4]; 42.81 + intcolor(color, icol); 42.82 + 42.83 + *pix++ = icol[0]; 42.84 + *pix++ = icol[1]; 42.85 + *pix++ = icol[2]; 42.86 + *pix++ = icol[3]; 42.87 + } 42.88 + } 42.89 + return img; 42.90 +} 42.91 + 42.92 + 42.93 +struct NoiseArg { 42.94 + int octaves; 42.95 + Vector4 col1, col2; 42.96 +}; 42.97 + 42.98 +static Vector4 fbm_eval(float x, float y, void *cls) 42.99 +{ 42.100 + NoiseArg *arg = (NoiseArg*)cls; 42.101 + 42.102 + float noise = fbm2(x, y, arg->octaves) * 0.5 + 0.5; 42.103 + return lerp(arg->col1, arg->col2, noise); 42.104 +} 42.105 + 42.106 +static Vector4 fbm_abs_eval(float x, float y, void *cls) 42.107 +{ 42.108 + NoiseArg *arg = (NoiseArg*)cls; 42.109 + 42.110 + float noise = turbulence2(x, y, arg->octaves) * 0.5 + 0.5; 42.111 + return lerp(arg->col1, arg->col2, noise); 42.112 +} 42.113 + 42.114 + 42.115 +Image *texgen_fbm(int xsz, int ysz, float usize, float vsize, int octaves, const Vector4 &col1, const Vector4 &col2) 42.116 +{ 42.117 + NoiseArg arg = {octaves, col1, col2}; 42.118 + if(arg.octaves < 1) { 42.119 + arg.octaves = 1; 42.120 + } 42.121 + 42.122 + return texgen(xsz, ysz, usize, vsize, fbm_eval, &arg); 42.123 +} 42.124 + 42.125 +Image *texgen_fbm_abs(int xsz, int ysz, float usize, float vsize, int octaves, const Vector4 &col1, const Vector4 &col2) 42.126 +{ 42.127 + NoiseArg arg = {octaves, col1, col2}; 42.128 + if(arg.octaves < 1) { 42.129 + arg.octaves = 1; 42.130 + } 42.131 + 42.132 + return texgen(xsz, ysz, usize, vsize, fbm_abs_eval, &arg); 42.133 +} 42.134 + 42.135 +static inline void intcolor(const Vector4 &color, int *icol) 42.136 +{ 42.137 + for(int i=0; i<4; i++) { 42.138 + icol[i] = std::max(std::min((int)(color[i] * 255.0), 255), 0); 42.139 + } 42.140 +}
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 43.2 +++ b/src/texgen.h Thu Nov 14 05:27:09 2013 +0200 43.3 @@ -0,0 +1,14 @@ 43.4 +#ifndef TEXGEN_H_ 43.5 +#define TEXGEN_H_ 43.6 + 43.7 +#include "image.h" 43.8 +#include "vmath/vmath.h" 43.9 + 43.10 +Image *texgen_solid(int xsz, int ysz, const Vector4 &color); 43.11 +Image *texgen_chess(int xsz, int ysz, int usub, int vsub, const Vector4 &col1, const Vector4 &col2); 43.12 +Image *texgen_fbm(int xsz, int ysz, float usize, float vsize, int octaves, const Vector4 &col1, const Vector4 &col2); 43.13 +Image *texgen_fbm_abs(int xsz, int ysz, float usize, float vsize, int octaves, const Vector4 &col1, const Vector4 &col2); 43.14 + 43.15 +Image *texgen(int xsz, int ysz, float usize, float vsize, Vector4 (*eval)(float, float, void*), void *cls); 43.16 + 43.17 +#endif // TEXGEN_H_
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 44.2 +++ b/src/texman.cc Thu Nov 14 05:27:09 2013 +0200 44.3 @@ -0,0 +1,3 @@ 44.4 +#include "texman.h" 44.5 + 44.6 +TextureSet texset;
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 45.2 +++ b/src/texman.h Thu Nov 14 05:27:09 2013 +0200 45.3 @@ -0,0 +1,8 @@ 45.4 +#ifndef TEXMAN_H_ 45.5 +#define TEXMAN_H_ 45.6 + 45.7 +#include "texture.h" 45.8 + 45.9 +extern TextureSet texset; 45.10 + 45.11 +#endif // TEXMAN_H_
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 46.2 +++ b/src/texture.cc Thu Nov 14 05:27:09 2013 +0200 46.3 @@ -0,0 +1,370 @@ 46.4 +#include "texture.h" 46.5 +#include "image.h" 46.6 +#include "opengl.h" 46.7 +#include "imago2.h" 46.8 +#include "logger.h" 46.9 +#include "datapath.h" 46.10 + 46.11 +static int glifmt_from_ifmt(unsigned int ifmt); 46.12 +static int glfmt_from_ifmt(unsigned int ifmt); 46.13 +static int gltype_from_ifmt(unsigned int ifmt); 46.14 + 46.15 +static int glifmt_from_imgfmt(Image::Format fmt); 46.16 + 46.17 +static unsigned int cur_target[8] = { 46.18 + GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, 46.19 + GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D 46.20 +}; 46.21 + 46.22 +void set_texture(Texture *tex, int tunit) 46.23 +{ 46.24 + if(tex) { 46.25 + tex->bind(tunit); 46.26 + } else { 46.27 + glActiveTexture(GL_TEXTURE0 + tunit); 46.28 + glBindTexture(cur_target[tunit], 0); 46.29 + glActiveTexture(GL_TEXTURE0); 46.30 + } 46.31 +} 46.32 + 46.33 +Texture *load_texture(const char *fname) 46.34 +{ 46.35 + TextureCube *texcube = new TextureCube; 46.36 + if(texcube->load(fname)) { 46.37 + return texcube; 46.38 + } 46.39 + delete texcube; 46.40 + 46.41 + Texture2D *tex = new Texture2D; 46.42 + if(tex->load(fname)) { 46.43 + return tex; 46.44 + } 46.45 + delete tex; 46.46 + return 0; 46.47 +} 46.48 + 46.49 + 46.50 +Texture::Texture() 46.51 +{ 46.52 + target = 0; 46.53 + sz[0] = sz[1] = sz[2] = 0; 46.54 + texfmt = 0; 46.55 + 46.56 + glGenTextures(1, &id); 46.57 +} 46.58 + 46.59 +Texture::~Texture() 46.60 +{ 46.61 + if(id) { 46.62 + glDeleteTextures(1, &id); 46.63 + } 46.64 +} 46.65 + 46.66 +void Texture::set_wrapping(unsigned int wrap) 46.67 +{ 46.68 + if(!target) { 46.69 + return; 46.70 + } 46.71 + 46.72 + glBindTexture(target, id); 46.73 + glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap); 46.74 + glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap); 46.75 +} 46.76 + 46.77 +void Texture::set_filtering(unsigned int filt) 46.78 +{ 46.79 + unsigned int mag_filter; 46.80 + 46.81 + if(!target) { 46.82 + return; 46.83 + } 46.84 + 46.85 + switch(filt) { 46.86 + case GL_LINEAR_MIPMAP_NEAREST: 46.87 + case GL_LINEAR_MIPMAP_LINEAR: 46.88 + mag_filter = GL_LINEAR; 46.89 + break; 46.90 + 46.91 + case GL_NEAREST_MIPMAP_NEAREST: 46.92 + case GL_NEAREST_MIPMAP_LINEAR: 46.93 + mag_filter = GL_NEAREST; 46.94 + break; 46.95 + 46.96 + default: 46.97 + mag_filter = filt; 46.98 + } 46.99 + 46.100 + set_filtering(filt, mag_filter); 46.101 +} 46.102 + 46.103 +void Texture::set_filtering(unsigned int min_filt, unsigned int mag_filt) 46.104 +{ 46.105 + glBindTexture(target, id); 46.106 + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, min_filt); 46.107 + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, mag_filt); 46.108 +} 46.109 + 46.110 +unsigned int Texture::get_format() const 46.111 +{ 46.112 + return texfmt; 46.113 +} 46.114 + 46.115 +int Texture::get_size(int dim) const 46.116 +{ 46.117 + if(dim < 0 || dim >= 3) { 46.118 + return 0; 46.119 + } 46.120 + return sz[dim]; 46.121 +} 46.122 + 46.123 +unsigned int Texture::get_id() const 46.124 +{ 46.125 + return id; 46.126 +} 46.127 + 46.128 +void Texture::bind(int tex_unit) const 46.129 +{ 46.130 + glActiveTexture(GL_TEXTURE0 + tex_unit); 46.131 + glBindTexture(target, id); 46.132 + glActiveTexture(GL_TEXTURE0); 46.133 + 46.134 + cur_target[tex_unit] = target; 46.135 +} 46.136 + 46.137 + 46.138 +// ---- Texture2D ---- 46.139 + 46.140 +Texture2D::Texture2D() 46.141 +{ 46.142 + target = GL_TEXTURE_2D; 46.143 +} 46.144 + 46.145 +void Texture2D::create(int xsz, int ysz, unsigned int ifmt) 46.146 +{ 46.147 + int fmt = glfmt_from_ifmt(ifmt); 46.148 + int type = gltype_from_ifmt(ifmt); 46.149 + 46.150 + glBindTexture(GL_TEXTURE_2D, id); 46.151 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 46.152 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 46.153 + glTexImage2D(GL_TEXTURE_2D, 0, glifmt_from_ifmt(ifmt), xsz, ysz, 0, fmt, type, 0); 46.154 + CHECKGLERR; 46.155 + sz[0] = xsz; 46.156 + sz[1] = ysz; 46.157 + texfmt = ifmt; 46.158 +} 46.159 + 46.160 +void Texture2D::set_image(const Image &img, int idx) 46.161 +{ 46.162 + texfmt = glifmt_from_imgfmt(img.get_format()); 46.163 + unsigned int fmt = glfmt_from_ifmt(texfmt); 46.164 + unsigned int type = gltype_from_ifmt(texfmt); 46.165 + 46.166 + sz[0] = img.get_width(); 46.167 + sz[1] = img.get_height(); 46.168 + 46.169 + glBindTexture(GL_TEXTURE_2D, id); 46.170 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 46.171 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 46.172 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 46.173 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 46.174 + 46.175 +#ifdef __GLEW_H__ 46.176 + if(GLEW_SGIS_generate_mipmap) { 46.177 + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); 46.178 +#endif 46.179 + glTexImage2D(GL_TEXTURE_2D, 0, texfmt, sz[0], sz[1], 0, fmt, type, img.get_pixels()); 46.180 +#ifdef __GLEW_H__ 46.181 + } else { 46.182 + gluBuild2DMipmaps(GL_TEXTURE_2D, texfmt, sz[0], sz[1], fmt, type, img.get_pixels()); 46.183 + } 46.184 +#endif 46.185 + 46.186 +#ifdef GL_ES_VERSION_2_0 46.187 + glGenerateMipmap(GL_TEXTURE_2D); 46.188 +#endif 46.189 +} 46.190 + 46.191 +bool Texture2D::load(const char *fname) 46.192 +{ 46.193 + Image img; 46.194 + if(!img.load(fname) == -1) { 46.195 + error_log("failed to load 2D texture: %s\n", fname); 46.196 + return false; 46.197 + } 46.198 + set_image(img); 46.199 + 46.200 + info_log("loaded 2D texture: %s\n", fname); 46.201 + return true; 46.202 +} 46.203 + 46.204 +bool Texture2D::save(const char *fname) const 46.205 +{ 46.206 +#ifndef GL_ES_VERSION_2_0 46.207 + unsigned char *pixels = new unsigned char[sz[0] * sz[1] * 4]; 46.208 + 46.209 + glBindTexture(GL_TEXTURE_2D, id); 46.210 + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 46.211 + 46.212 + if(img_save_pixels(fname, pixels, sz[0], sz[1]) == -1) { 46.213 + error_log("failed to save 2D texture: %s\n", fname); 46.214 + delete [] pixels; 46.215 + return false; 46.216 + } 46.217 + 46.218 + info_log("saved 2D texture: %s\n", fname); 46.219 + delete [] pixels; 46.220 + return true; 46.221 +#else 46.222 + return false; // TODO 46.223 +#endif 46.224 +} 46.225 + 46.226 +// ---- TextureCube ---- 46.227 +static unsigned int cube_faces[] = { 46.228 + GL_TEXTURE_CUBE_MAP_POSITIVE_X, 46.229 + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 46.230 + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 46.231 + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 46.232 + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 46.233 + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 46.234 +}; 46.235 + 46.236 +TextureCube::TextureCube() 46.237 +{ 46.238 + target = GL_TEXTURE_CUBE_MAP; 46.239 +} 46.240 + 46.241 +void TextureCube::create(int xsz, int ysz, unsigned int ifmt) 46.242 +{ 46.243 + if(xsz != ysz) { 46.244 + error_log("trying to create cubemap with different width and height (%dx%d)\n", xsz, ysz); 46.245 + return; 46.246 + } 46.247 + 46.248 + texfmt = ifmt; 46.249 + 46.250 + glBindTexture(GL_TEXTURE_CUBE_MAP, id); 46.251 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 46.252 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 46.253 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 46.254 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 46.255 + 46.256 + for(int i=0; i<6; i++) { 46.257 + glTexImage2D(cube_faces[i], 0, ifmt, xsz, ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); 46.258 + } 46.259 +} 46.260 + 46.261 +void TextureCube::set_image(const Image &img, int idx) 46.262 +{ 46.263 + // TODO 46.264 +} 46.265 + 46.266 +bool TextureCube::load(const char *fname) 46.267 +{ 46.268 + return false; // TODO 46.269 +} 46.270 + 46.271 +bool TextureCube::save(const char *fname) const 46.272 +{ 46.273 + return false; // TODO 46.274 +} 46.275 + 46.276 +static int glifmt_from_ifmt(unsigned int ifmt) 46.277 +{ 46.278 +#ifdef GL_ES_VERSION_2_0 46.279 + switch(ifmt) { 46.280 + case GL_LUMINANCE16F: 46.281 + case GL_LUMINANCE32F: 46.282 + ifmt = GL_LUMINANCE; 46.283 + break; 46.284 + 46.285 + case GL_RGB16F: 46.286 + case GL_RGB32F: 46.287 + ifmt = GL_RGB; 46.288 + break; 46.289 + 46.290 + case GL_RGBA16F: 46.291 + case GL_RGBA32F: 46.292 + ifmt = GL_RGBA; 46.293 + break; 46.294 + 46.295 + default: 46.296 + break; 46.297 + } 46.298 +#endif 46.299 + return ifmt; // by default just pass it through... 46.300 +} 46.301 + 46.302 +static int glfmt_from_ifmt(unsigned int ifmt) 46.303 +{ 46.304 + switch(ifmt) { 46.305 + case GL_LUMINANCE16F: 46.306 + case GL_LUMINANCE32F: 46.307 + return GL_LUMINANCE; 46.308 + 46.309 + case GL_RGB16F: 46.310 + case GL_RGB32F: 46.311 + return GL_RGB; 46.312 + 46.313 + case GL_RGBA16F: 46.314 + case GL_RGBA32F: 46.315 + return GL_RGBA; 46.316 + 46.317 + default: 46.318 + break; 46.319 + } 46.320 + return ifmt; 46.321 +} 46.322 + 46.323 +static int gltype_from_ifmt(unsigned int ifmt) 46.324 +{ 46.325 + switch(ifmt) { 46.326 + case GL_RGB16F: 46.327 + case GL_RGBA16F: 46.328 + case GL_LUMINANCE16F: 46.329 +#ifdef GL_ES_VERSION_2_0 46.330 + return GL_HALF_FLOAT_OES; 46.331 +#endif 46.332 + case GL_RGB32F: 46.333 + case GL_RGBA32F: 46.334 + case GL_LUMINANCE32F: 46.335 + return GL_FLOAT; 46.336 + 46.337 + default: 46.338 + break; 46.339 + } 46.340 + return GL_UNSIGNED_BYTE; 46.341 +} 46.342 + 46.343 +static int glifmt_from_imgfmt(Image::Format fmt) 46.344 +{ 46.345 + switch(fmt) { 46.346 + case Image::FMT_GREY: 46.347 + return GL_LUMINANCE; 46.348 + case Image::FMT_GREY_FLOAT: 46.349 + return GL_LUMINANCE16F; 46.350 + case Image::FMT_RGB: 46.351 + return GL_RGB; 46.352 + case Image::FMT_RGB_FLOAT: 46.353 + return GL_RGB16F; 46.354 + case Image::FMT_RGBA: 46.355 + return GL_RGBA; 46.356 + case Image::FMT_RGBA_FLOAT: 46.357 + return GL_RGBA16F; 46.358 + default: 46.359 + break; 46.360 + } 46.361 + return 0; 46.362 +} 46.363 + 46.364 +// ---- TextureSet ---- 46.365 +static void destroy_texture(Texture *tex) 46.366 +{ 46.367 + delete tex; 46.368 +} 46.369 + 46.370 +TextureSet::TextureSet() 46.371 + : DataSet<Texture*>(load_texture, destroy_texture) 46.372 +{ 46.373 +}
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 47.2 +++ b/src/texture.h Thu Nov 14 05:27:09 2013 +0200 47.3 @@ -0,0 +1,76 @@ 47.4 +#ifndef TEXTURE_H_ 47.5 +#define TEXTURE_H_ 47.6 + 47.7 +#include "dataset.h" 47.8 +#include "opengl.h" 47.9 + 47.10 +class Image; 47.11 + 47.12 +class Texture { 47.13 +protected: 47.14 + unsigned int id; 47.15 + unsigned int target; 47.16 + unsigned int texfmt; 47.17 + int sz[3]; 47.18 + 47.19 + Texture(const Texture &tex) {} 47.20 + Texture &operator =(const Texture &tex) { return *this; } 47.21 + 47.22 +public: 47.23 + Texture(); 47.24 + virtual ~Texture(); 47.25 + 47.26 + void set_wrapping(unsigned int wrap); 47.27 + void set_filtering(unsigned int filt); 47.28 + void set_filtering(unsigned int min_filt, unsigned int mag_filt); 47.29 + 47.30 + unsigned int get_format() const; 47.31 + 47.32 + virtual int get_size(int dim) const; 47.33 + 47.34 + virtual void create(int xsz, int ysz, unsigned int ifmt = GL_RGBA) = 0; 47.35 + virtual void set_image(const Image &img, int idx = 0) = 0; 47.36 + 47.37 + virtual bool load(const char *fname) = 0; 47.38 + virtual bool save(const char *fname) const = 0; 47.39 + 47.40 + virtual unsigned int get_id() const; 47.41 + 47.42 + virtual void bind(int tex_unit = 0) const; 47.43 +}; 47.44 + 47.45 +class Texture2D : public Texture { 47.46 +public: 47.47 + Texture2D(); 47.48 + 47.49 + virtual void create(int xsz, int ysz, unsigned int ifmt = GL_RGBA); 47.50 + virtual void set_image(const Image &img, int idx = 0); 47.51 + 47.52 + virtual bool load(const char *fname); 47.53 + virtual bool save(const char *fname) const; 47.54 +}; 47.55 + 47.56 +class TextureCube : public Texture { 47.57 +public: 47.58 + TextureCube(); 47.59 + 47.60 + virtual void create(int xsz, int ysz, unsigned int ifmt = GL_RGBA); 47.61 + virtual void set_image(const Image &img, int idx = 0); 47.62 + 47.63 + virtual bool load(const char *fname); 47.64 + virtual bool save(const char *fname) const; 47.65 +}; 47.66 + 47.67 +void set_texture(Texture *tex, int tunit = 0); 47.68 + 47.69 +/** loads a texture autodetecting whether it's a 2D texture or 47.70 + * cubemap and creating the correct Texture subclass instance. 47.71 + */ 47.72 +Texture *load_texture(const char *fname); 47.73 + 47.74 +class TextureSet : public DataSet<Texture*> { 47.75 +public: 47.76 + TextureSet(); 47.77 +}; 47.78 + 47.79 +#endif // TEXTURE_H_
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 48.2 +++ b/src/timer.cc Thu Nov 14 05:27:09 2013 +0200 48.3 @@ -0,0 +1,118 @@ 48.4 +#include "timer.h" 48.5 + 48.6 +#if defined(__APPLE__) && !defined(__unix__) 48.7 +#define __unix__ 48.8 +#endif 48.9 + 48.10 +#ifdef __unix__ 48.11 +#include <time.h> 48.12 +#include <unistd.h> 48.13 +#include <sys/time.h> 48.14 + 48.15 +#ifdef CLOCK_MONOTONIC 48.16 +unsigned long get_time_msec(void) 48.17 +{ 48.18 + struct timespec ts; 48.19 + static struct timespec ts0; 48.20 + 48.21 + clock_gettime(CLOCK_MONOTONIC, &ts); 48.22 + if(ts0.tv_sec == 0 && ts0.tv_nsec == 0) { 48.23 + ts0 = ts; 48.24 + return 0; 48.25 + } 48.26 + return (ts.tv_sec - ts0.tv_sec) * 1000 + (ts.tv_nsec - ts0.tv_nsec) / 1000000; 48.27 +} 48.28 +#else /* no fancy POSIX clocks, fallback to good'ol gettimeofday */ 48.29 +unsigned long get_time_msec(void) 48.30 +{ 48.31 + struct timeval tv; 48.32 + static struct timeval tv0; 48.33 + 48.34 + gettimeofday(&tv, 0); 48.35 + if(tv0.tv_sec == 0 && tv0.tv_usec == 0) { 48.36 + tv0 = tv; 48.37 + return 0; 48.38 + } 48.39 + return (tv.tv_sec - tv0.tv_sec) * 1000 + (tv.tv_usec - tv0.tv_usec) / 1000; 48.40 +} 48.41 +#endif /* !posix clock */ 48.42 + 48.43 +void sleep_msec(unsigned long msec) 48.44 +{ 48.45 + usleep(msec * 1000); 48.46 +} 48.47 +#endif 48.48 + 48.49 +#ifdef WIN32 48.50 +#include <windows.h> 48.51 +#pragma comment(lib, "winmm.lib") 48.52 + 48.53 +unsigned long get_time_msec(void) 48.54 +{ 48.55 + return timeGetTime(); 48.56 +} 48.57 + 48.58 +void sleep_msec(unsigned long msec) 48.59 +{ 48.60 + Sleep(msec); 48.61 +} 48.62 +#endif 48.63 + 48.64 +double get_time_sec(void) 48.65 +{ 48.66 + return get_time_msec() / 1000.0f; 48.67 +} 48.68 + 48.69 +void sleep_sec(double sec) 48.70 +{ 48.71 + if(sec > 0.0f) { 48.72 + sleep_msec(sec * 1000.0f); 48.73 + } 48.74 +} 48.75 + 48.76 + 48.77 +Timer::Timer() 48.78 +{ 48.79 + reset(); 48.80 +} 48.81 + 48.82 +void Timer::reset() 48.83 +{ 48.84 + pause_time = 0; 48.85 + start_time = get_time_msec(); 48.86 +} 48.87 + 48.88 +void Timer::start() 48.89 +{ 48.90 + if(!is_running()) { 48.91 + // resuming 48.92 + start_time += get_time_msec() - pause_time; 48.93 + pause_time = 0; 48.94 + } 48.95 +} 48.96 + 48.97 +void Timer::stop() 48.98 +{ 48.99 + if(is_running()) { 48.100 + pause_time = get_time_msec(); 48.101 + } 48.102 +} 48.103 + 48.104 +bool Timer::is_running() const 48.105 +{ 48.106 + return pause_time == 0; 48.107 +} 48.108 + 48.109 +unsigned long Timer::get_msec() const 48.110 +{ 48.111 + if(!is_running()) { 48.112 + // in paused state... 48.113 + return pause_time - start_time; 48.114 + } 48.115 + return get_time_msec() - start_time; 48.116 +} 48.117 + 48.118 +double Timer::get_sec() const 48.119 +{ 48.120 + return (double)get_msec() / 1000.0; 48.121 +}
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 49.2 +++ b/src/timer.h Thu Nov 14 05:27:09 2013 +0200 49.3 @@ -0,0 +1,29 @@ 49.4 +#ifndef TIMER_H_ 49.5 +#define TIMER_H_ 49.6 + 49.7 +unsigned long get_time_msec(void); 49.8 +void sleep_msec(unsigned long msec); 49.9 + 49.10 +double get_time_sec(void); 49.11 +void sleep_sec(double sec); 49.12 + 49.13 + 49.14 +class Timer { 49.15 +private: 49.16 + unsigned long start_time, pause_time; 49.17 + 49.18 +public: 49.19 + Timer(); 49.20 + 49.21 + void reset(); 49.22 + 49.23 + void start(); 49.24 + void stop(); 49.25 + 49.26 + bool is_running() const; 49.27 + 49.28 + unsigned long get_msec() const; 49.29 + double get_sec() const; 49.30 +}; 49.31 + 49.32 +#endif // TIMER_H_
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 50.2 +++ b/src/unistate.cc Thu Nov 14 05:27:09 2013 +0200 50.3 @@ -0,0 +1,678 @@ 50.4 +#include <map> 50.5 +#include <vector> 50.6 +#include "unistate.h" 50.7 +#include "shader.h" 50.8 +#include "logger.h" 50.9 + 50.10 +struct StateItem { 50.11 + StType type; 50.12 + 50.13 + union { 50.14 + int ival[4]; 50.15 + float fval[16]; 50.16 + }; 50.17 + int transpose; // for matrices 50.18 +}; 50.19 + 50.20 +static const char *typestr(StType type); 50.21 +static int type_nelem(StType type); 50.22 +static StType float_type(int elem); 50.23 +static StType int_type(int elem); 50.24 + 50.25 +std::vector<StateItem> state; 50.26 +std::map<std::string, int> stateidx; 50.27 + 50.28 + 50.29 +int add_unistate(const char *name, StType type) 50.30 +{ 50.31 + static const float ident3[] = {1, 0, 0, 0, 1, 0, 0, 0, 1}; 50.32 + static const float ident4[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; 50.33 + 50.34 + if(stateidx.find(name) != stateidx.end()) { 50.35 + return stateidx[name]; 50.36 + } 50.37 + 50.38 + StateItem sitem; 50.39 + memset(&sitem, 0, sizeof sitem); 50.40 + sitem.type = type; 50.41 + 50.42 + // initialize to a reasonable default value 50.43 + switch(type) { 50.44 + case ST_MATRIX3: 50.45 + memcpy(sitem.fval, ident3, sizeof ident3); 50.46 + break; 50.47 + 50.48 + case ST_MATRIX4: 50.49 + memcpy(sitem.fval, ident4, sizeof ident4); 50.50 + break; 50.51 + 50.52 + default: 50.53 + break; // in all other cases leave it zero (see memset above) 50.54 + } 50.55 + 50.56 + int sidx = state.size(); 50.57 + state.push_back(sitem); 50.58 + stateidx[name] = sidx; 50.59 + 50.60 + debug_log("adding uniform state [%d]: %s %s\n", sidx, typestr(sitem.type), name); 50.61 + 50.62 + return sidx; 50.63 +} 50.64 + 50.65 +int get_unistate_index(const char *name) 50.66 +{ 50.67 + std::map<std::string, int>::const_iterator it = stateidx.find(name); 50.68 + if(it != stateidx.end()) { 50.69 + return it->second; 50.70 + } 50.71 + return -1; 50.72 +} 50.73 + 50.74 +#define CHECK_INDEX(i) \ 50.75 + if(i < 0 || i >= (int)state.size()) return 50.76 + 50.77 +#define CHECK_COUNT(count, type) \ 50.78 + do { \ 50.79 + int max_elem = type_nelem(type); \ 50.80 + if(!(count) || (count) > max_elem) { \ 50.81 + count = max_elem; \ 50.82 + } \ 50.83 + } while(0) 50.84 + 50.85 +void set_unistate(int sidx, const int *val, int count) 50.86 +{ 50.87 + CHECK_INDEX(sidx); 50.88 + CHECK_COUNT(count, state[sidx].type); 50.89 + 50.90 + memcpy(state[sidx].ival, val, count * sizeof *state[sidx].ival); 50.91 +} 50.92 + 50.93 +void set_unistate(int sidx, const float *val, int count) 50.94 +{ 50.95 + CHECK_INDEX(sidx); 50.96 + CHECK_COUNT(count, state[sidx].type); 50.97 + 50.98 + memcpy(state[sidx].fval, val, count * sizeof *state[sidx].fval); 50.99 + state[sidx].transpose = 0; 50.100 +} 50.101 + 50.102 +void get_unistate(int sidx, int *val, int count) 50.103 +{ 50.104 + CHECK_INDEX(sidx); 50.105 + CHECK_COUNT(count, state[sidx].type); 50.106 + 50.107 + memcpy(val, state[sidx].ival, count * sizeof *val); 50.108 +} 50.109 + 50.110 +void get_unistate(int sidx, float *val, int count) 50.111 +{ 50.112 + CHECK_INDEX(sidx); 50.113 + CHECK_COUNT(count, state[sidx].type); 50.114 + 50.115 + memcpy(val, state[sidx].fval, count * sizeof *val); 50.116 +} 50.117 + 50.118 +void set_unistate(int sidx, int val) 50.119 +{ 50.120 + set_unistate(sidx, &val, 1); 50.121 +} 50.122 + 50.123 +void set_unistate(int sidx, float val) 50.124 +{ 50.125 + set_unistate(sidx, &val, 1); 50.126 +} 50.127 + 50.128 +void set_unistate(int sidx, const Vector2 &vec) 50.129 +{ 50.130 + set_unistate(sidx, &vec.x, 2); 50.131 +} 50.132 + 50.133 +void set_unistate(int sidx, const Vector3 &vec) 50.134 +{ 50.135 + set_unistate(sidx, &vec.x, 3); 50.136 +} 50.137 + 50.138 +void set_unistate(int sidx, const Vector4 &vec) 50.139 +{ 50.140 + set_unistate(sidx, &vec.x, 4); 50.141 +} 50.142 + 50.143 +void set_unistate(int sidx, const Matrix3x3 &mat) 50.144 +{ 50.145 + set_unistate(sidx, mat[0], 9); 50.146 + state[sidx].transpose = 1; 50.147 +} 50.148 + 50.149 +void set_unistate(int sidx, const Matrix4x4 &mat) 50.150 +{ 50.151 + set_unistate(sidx, mat[0], 16); 50.152 + state[sidx].transpose = 1; 50.153 +} 50.154 + 50.155 + 50.156 +int set_unistate(const char *name, int *val, int count) 50.157 +{ 50.158 + int sidx = get_unistate_index(name); 50.159 + if(sidx < 0) { 50.160 + StType type = int_type(count); 50.161 + if(type == ST_UNKNOWN) { 50.162 + error_log("invalid element count (%d) while setting previously unknown unistate item \"%s\"\n", 50.163 + count, name); 50.164 + return -1; 50.165 + } 50.166 + 50.167 + sidx = add_unistate(name, type); 50.168 + } 50.169 + set_unistate(sidx, val); 50.170 + return sidx; 50.171 +} 50.172 + 50.173 +int set_unistate(const char *name, float *val, int count) 50.174 +{ 50.175 + int sidx = get_unistate_index(name); 50.176 + if(sidx < 0) { 50.177 + StType type = float_type(count); 50.178 + if(type == ST_UNKNOWN) { 50.179 + error_log("invalid element count (%d) while setting previously unknown unistate item \"%s\"\n", 50.180 + count, name); 50.181 + return -1; 50.182 + } 50.183 + 50.184 + sidx = add_unistate(name, type); 50.185 + } 50.186 + set_unistate(sidx, val); 50.187 + return sidx; 50.188 +} 50.189 + 50.190 +int set_unistate(const char *name, int val) 50.191 +{ 50.192 + int sidx = get_unistate_index(name); 50.193 + if(sidx < 0) { 50.194 + sidx = add_unistate(name, ST_INT); 50.195 + } 50.196 + set_unistate(sidx, val); 50.197 + return sidx; 50.198 +} 50.199 + 50.200 +int set_unistate(const char *name, float val) 50.201 +{ 50.202 + int sidx = get_unistate_index(name); 50.203 + if(sidx < 0) { 50.204 + sidx = add_unistate(name, ST_FLOAT); 50.205 + } 50.206 + set_unistate(sidx, val); 50.207 + return sidx; 50.208 +} 50.209 + 50.210 +int set_unistate(const char *name, const Vector2 &vec) 50.211 +{ 50.212 + int sidx = get_unistate_index(name); 50.213 + if(sidx < 0) { 50.214 + sidx = add_unistate(name, ST_FLOAT2); 50.215 + } 50.216 + set_unistate(sidx, vec); 50.217 + return sidx; 50.218 +} 50.219 + 50.220 +int set_unistate(const char *name, const Vector3 &vec) 50.221 +{ 50.222 + int sidx = get_unistate_index(name); 50.223 + if(sidx < 0) { 50.224 + sidx = add_unistate(name, ST_FLOAT3); 50.225 + } 50.226 + set_unistate(sidx, vec); 50.227 + return sidx; 50.228 +} 50.229 + 50.230 +int set_unistate(const char *name, const Vector4 &vec) 50.231 +{ 50.232 + int sidx = get_unistate_index(name); 50.233 + if(sidx < 0) { 50.234 + sidx = add_unistate(name, ST_FLOAT4); 50.235 + } 50.236 + set_unistate(sidx, vec); 50.237 + return sidx; 50.238 +} 50.239 + 50.240 +int set_unistate(const char *name, const Matrix3x3 &mat) 50.241 +{ 50.242 + int sidx = get_unistate_index(name); 50.243 + if(sidx < 0) { 50.244 + sidx = add_unistate(name, ST_MATRIX3); 50.245 + } 50.246 + set_unistate(sidx, mat); 50.247 + return sidx; 50.248 +} 50.249 + 50.250 +int set_unistate(const char *name, const Matrix4x4 &mat) 50.251 +{ 50.252 + int sidx = get_unistate_index(name); 50.253 + if(sidx < 0) { 50.254 + sidx = add_unistate(name, ST_MATRIX4); 50.255 + } 50.256 + set_unistate(sidx, mat); 50.257 + return sidx; 50.258 +} 50.259 + 50.260 + 50.261 +int get_unistate_int(int sidx) 50.262 +{ 50.263 + int val = 0; 50.264 + get_unistate(sidx, &val, 1); 50.265 + return val; 50.266 +} 50.267 + 50.268 +float get_unistate_float(int sidx) 50.269 +{ 50.270 + float val = 0.0f; 50.271 + get_unistate(sidx, &val, 1); 50.272 + return val; 50.273 +} 50.274 + 50.275 +Vector2 get_unistate_vec2(int sidx) 50.276 +{ 50.277 + float val[2] = {0.0f, 0.0f}; 50.278 + get_unistate(sidx, val, 2); 50.279 + return Vector2(val[0], val[1]); 50.280 +} 50.281 + 50.282 +Vector3 get_unistate_vec3(int sidx) 50.283 +{ 50.284 + float val[3] = {0.0f, 0.0f, 0.0f}; 50.285 + get_unistate(sidx, val, 3); 50.286 + return Vector3(val[0], val[1], val[2]); 50.287 +} 50.288 + 50.289 +Vector4 get_unistate_vec4(int sidx) 50.290 +{ 50.291 + float val[4] = {0.0f, 0.0f, 0.0f}; 50.292 + get_unistate(sidx, val, 4); 50.293 + return Vector4(val[0], val[1], val[2], val[3]); 50.294 +} 50.295 + 50.296 +Matrix3x3 get_unistate_mat3(int sidx) 50.297 +{ 50.298 + Matrix3x3 res; 50.299 + get_unistate(sidx, res.m[0], 9); 50.300 + return res; 50.301 +} 50.302 + 50.303 +Matrix4x4 get_unistate_mat4(int sidx) 50.304 +{ 50.305 + Matrix4x4 res; 50.306 + get_unistate(sidx, res.m[0], 16); 50.307 + return res; 50.308 +} 50.309 + 50.310 + 50.311 +int get_unistate_int(const char *name) 50.312 +{ 50.313 + int sidx = get_unistate_index(name); 50.314 + if(sidx == -1) { 50.315 + return 0; 50.316 + } 50.317 + return get_unistate_int(sidx); 50.318 +} 50.319 + 50.320 +float get_unistate_float(const char *name) 50.321 +{ 50.322 + int sidx = get_unistate_index(name); 50.323 + if(sidx == -1) { 50.324 + return 0.0f; 50.325 + } 50.326 + return get_unistate_float(sidx); 50.327 +} 50.328 + 50.329 +Vector2 get_unistate_vec2(const char *name) 50.330 +{ 50.331 + int sidx = get_unistate_index(name); 50.332 + if(sidx == -1) { 50.333 + return Vector2(); 50.334 + } 50.335 + return get_unistate_vec2(sidx); 50.336 +} 50.337 + 50.338 +Vector3 get_unistate_vec3(const char *name) 50.339 +{ 50.340 + int sidx = get_unistate_index(name); 50.341 + if(sidx == -1) { 50.342 + return Vector3(); 50.343 + } 50.344 + return get_unistate_vec3(sidx); 50.345 +} 50.346 + 50.347 +Vector4 get_unistate_vec4(const char *name) 50.348 +{ 50.349 + int sidx = get_unistate_index(name); 50.350 + if(sidx == -1) { 50.351 + return Vector4(); 50.352 + } 50.353 + return get_unistate_vec4(sidx); 50.354 +} 50.355 + 50.356 +Matrix3x3 get_unistate_mat3(const char *name) 50.357 +{ 50.358 + int sidx = get_unistate_index(name); 50.359 + if(sidx == -1) { 50.360 + return Matrix3x3(); 50.361 + } 50.362 + return get_unistate_mat3(sidx); 50.363 +} 50.364 + 50.365 +Matrix4x4 get_unistate_mat4(const char *name) 50.366 +{ 50.367 + int sidx = get_unistate_index(name); 50.368 + if(sidx == -1) { 50.369 + return Matrix4x4(); 50.370 + } 50.371 + return get_unistate_mat4(sidx); 50.372 +} 50.373 + 50.374 + 50.375 +void setup_unistate(const ShaderProg *sdr) 50.376 +{ 50.377 + if(!sdr) { 50.378 + if(!(sdr = ShaderProg::current)) { 50.379 + return; 50.380 + } 50.381 + } 50.382 + 50.383 + sdr->setup_state_uniforms(); 50.384 +} 50.385 + 50.386 +bool setup_unistate(int sidx, const ShaderProg *sdr, int loc) 50.387 +{ 50.388 + if(loc < 0 || sidx < 0 || sidx >= (int)state.size()) { 50.389 + return false; 50.390 + } 50.391 + 50.392 + CHECKGLERR; 50.393 + glUseProgram(sdr->get_id()); 50.394 + CHECKGLERR; 50.395 + 50.396 + switch(state[sidx].type) { 50.397 + case ST_INT: 50.398 + glUniform1iv(loc, 1, state[sidx].ival); 50.399 + break; 50.400 + case ST_INT2: 50.401 + glUniform2iv(loc, 1, state[sidx].ival); 50.402 + break; 50.403 + case ST_INT3: 50.404 + glUniform3iv(loc, 1, state[sidx].ival); 50.405 + break; 50.406 + case ST_INT4: 50.407 + glUniform4iv(loc, 1, state[sidx].ival); 50.408 + break; 50.409 + 50.410 + case ST_FLOAT: 50.411 + glUniform1fv(loc, 1, state[sidx].fval); 50.412 + break; 50.413 + case ST_FLOAT2: 50.414 + glUniform2fv(loc, 1, state[sidx].fval); 50.415 + break; 50.416 + case ST_FLOAT3: 50.417 + glUniform3fv(loc, 1, state[sidx].fval); 50.418 + break; 50.419 + case ST_FLOAT4: 50.420 + glUniform4fv(loc, 1, state[sidx].fval); 50.421 + break; 50.422 + 50.423 + case ST_MATRIX3: 50.424 +#ifdef GL_ES_VERSION_2_0 50.425 + { 50.426 + float tmat[9], *ptr = tmat; 50.427 + for(int i=0; i<3; i++) { 50.428 + for(int j=0; j<3; j++) { 50.429 + *ptr++ = state[sidx].fval[j * 3 + i]; 50.430 + } 50.431 + } 50.432 + glUniformMatrix3fv(loc, 1, GL_FALSE, tmat); 50.433 + } 50.434 +#else 50.435 + glUniformMatrix3fv(loc, 1, state[sidx].transpose, state[sidx].fval); 50.436 +#endif 50.437 + break; 50.438 + 50.439 + case ST_MATRIX4: 50.440 +#ifdef GL_ES_VERSION_2_0 50.441 + { 50.442 + float tmat[16], *ptr = tmat; 50.443 + for(int i=0; i<4; i++) { 50.444 + for(int j=0; j<4; j++) { 50.445 + *ptr++ = state[sidx].fval[j * 4 + i]; 50.446 + } 50.447 + } 50.448 + glUniformMatrix4fv(loc, 1, GL_FALSE, tmat); 50.449 + } 50.450 +#else 50.451 + glUniformMatrix4fv(loc, 1, state[sidx].transpose, state[sidx].fval); 50.452 +#endif 50.453 + break; 50.454 + 50.455 + default: 50.456 + return false; 50.457 + } 50.458 + 50.459 + CHECKGLERR; 50.460 + return true; 50.461 +} 50.462 + 50.463 +bool setup_unistate(const char *name, const ShaderProg *sdr) 50.464 +{ 50.465 + int loc = sdr->get_uniform_location(name); 50.466 + if(loc == -1) { 50.467 + return false; 50.468 + } 50.469 + return setup_unistate(get_unistate_index(name), sdr, loc); 50.470 +} 50.471 + 50.472 +void set_world_matrix(const Matrix4x4 &mat) 50.473 +{ 50.474 + static int sidx = -1, sidx_transp, sidx_mat3; 50.475 + 50.476 + if(sidx == -1) { 50.477 + sidx = add_unistate("st_world_matrix", ST_MATRIX4); 50.478 + sidx_mat3 = add_unistate("st_world_matrix3", ST_MATRIX3); 50.479 + sidx_transp = add_unistate("st_world_matrix_transpose", ST_MATRIX4); 50.480 + } 50.481 + 50.482 + set_unistate(sidx, mat); 50.483 + set_unistate(sidx_mat3, Matrix3x3(mat)); 50.484 + set_unistate(sidx_transp, mat[0]); // by using the float* variant, we unset the transpose flag 50.485 +} 50.486 + 50.487 +void set_view_matrix(const Matrix4x4 &mat) 50.488 +{ 50.489 + static int sidx = -1, sidx_transp, sidx_mat3; 50.490 + 50.491 + if(sidx == -1) { 50.492 + sidx = add_unistate("st_view_matrix", ST_MATRIX4); 50.493 + sidx_mat3 = add_unistate("st_view_matrix3", ST_MATRIX3); 50.494 + sidx_transp = add_unistate("st_view_matrix_transpose", ST_MATRIX4); 50.495 + } 50.496 + 50.497 + set_unistate(sidx, mat); 50.498 + set_unistate(sidx_mat3, Matrix3x3(mat)); 50.499 + set_unistate(sidx_transp, mat[0]); // by using the float* variant, we unset the transpose flag 50.500 +} 50.501 + 50.502 +void set_projection_matrix(const Matrix4x4 &mat) 50.503 +{ 50.504 + static int sidx = -1; 50.505 + 50.506 + if(sidx == -1) { 50.507 + sidx = add_unistate("st_proj_matrix", ST_MATRIX4); 50.508 + } 50.509 + 50.510 + set_unistate(sidx, mat); 50.511 +} 50.512 + 50.513 +void set_texture_matrix(const Matrix4x4 &mat) 50.514 +{ 50.515 + static int sidx = -1; 50.516 + 50.517 + if(sidx == -1) { 50.518 + sidx = add_unistate("st_tex_matrix", ST_MATRIX4); 50.519 + } 50.520 + 50.521 + set_unistate(sidx, mat); 50.522 +} 50.523 + 50.524 +Matrix4x4 get_world_matrix() 50.525 +{ 50.526 + static int sidx = -1; 50.527 + 50.528 + if(sidx == -1) { 50.529 + if((sidx = get_unistate_index("st_world_matrix")) == -1) { 50.530 + return Matrix4x4(); 50.531 + } 50.532 + } 50.533 + return get_unistate_mat4(sidx); 50.534 +} 50.535 + 50.536 +Matrix4x4 get_view_matrix() 50.537 +{ 50.538 + static int sidx = -1; 50.539 + 50.540 + if(sidx == -1) { 50.541 + if((sidx = get_unistate_index("st_view_matrix")) == -1) { 50.542 + return Matrix4x4(); 50.543 + } 50.544 + } 50.545 + return get_unistate_mat4(sidx); 50.546 +} 50.547 + 50.548 +Matrix4x4 get_projection_matrix() 50.549 +{ 50.550 + static int sidx = -1; 50.551 + 50.552 + if(sidx == -1) { 50.553 + if((sidx = get_unistate_index("st_proj_matrix")) == -1) { 50.554 + return Matrix4x4(); 50.555 + } 50.556 + } 50.557 + return get_unistate_mat4(sidx); 50.558 +} 50.559 + 50.560 +Matrix4x4 get_texture_matrix() 50.561 +{ 50.562 + static int sidx = -1; 50.563 + 50.564 + if(sidx == -1) { 50.565 + if((sidx = get_unistate_index("st_tex_matrix")) == -1) { 50.566 + return Matrix4x4(); 50.567 + } 50.568 + } 50.569 + return get_unistate_mat4(sidx); 50.570 +} 50.571 + 50.572 +void setup_gl_matrices() 50.573 +{ 50.574 +#ifdef USE_OLDGL 50.575 + Matrix4x4 modelview = get_world_matrix() * get_view_matrix(); 50.576 + Matrix4x4 proj = get_projection_matrix(); 50.577 + Matrix4x4 tex = get_texture_matrix(); 50.578 + 50.579 + glMatrixMode(GL_TEXTURE); 50.580 + glLoadTransposeMatrixf(tex[0]); 50.581 + glMatrixMode(GL_PROJECTION); 50.582 + glLoadTransposeMatrixf(proj[0]); 50.583 + glMatrixMode(GL_MODELVIEW); 50.584 + glLoadTransposeMatrixf(modelview[0]); 50.585 +#endif 50.586 +} 50.587 + 50.588 +static const char *typestr(StType type) 50.589 +{ 50.590 + switch(type) { 50.591 + case ST_INT: 50.592 + return "int"; 50.593 + case ST_INT2: 50.594 + return "ivec2"; 50.595 + case ST_INT3: 50.596 + return "ivec3"; 50.597 + case ST_INT4: 50.598 + return "ivec4"; 50.599 + case ST_FLOAT: 50.600 + return "float"; 50.601 + case ST_FLOAT2: 50.602 + return "vec2"; 50.603 + case ST_FLOAT3: 50.604 + return "vec3"; 50.605 + case ST_FLOAT4: 50.606 + return "vec4"; 50.607 + case ST_MATRIX3: 50.608 + return "mat3"; 50.609 + case ST_MATRIX4: 50.610 + return "mat4"; 50.611 + 50.612 + default: 50.613 + break; 50.614 + } 50.615 + return "<unknown>"; 50.616 +} 50.617 + 50.618 +static int type_nelem(StType type) 50.619 +{ 50.620 + switch(type) { 50.621 + case ST_INT: 50.622 + case ST_FLOAT: 50.623 + return 1; 50.624 + case ST_INT2: 50.625 + case ST_FLOAT2: 50.626 + return 2; 50.627 + case ST_INT3: 50.628 + case ST_FLOAT3: 50.629 + return 3; 50.630 + case ST_INT4: 50.631 + case ST_FLOAT4: 50.632 + return 4; 50.633 + case ST_MATRIX3: 50.634 + return 9; 50.635 + case ST_MATRIX4: 50.636 + return 16; 50.637 + 50.638 + default: 50.639 + break; 50.640 + } 50.641 + 50.642 + return 0; 50.643 +} 50.644 + 50.645 +static StType float_type(int elem) 50.646 +{ 50.647 + switch(elem) { 50.648 + case 1: 50.649 + return ST_FLOAT; 50.650 + case 2: 50.651 + return ST_FLOAT2; 50.652 + case 3: 50.653 + return ST_FLOAT3; 50.654 + case 4: 50.655 + return ST_FLOAT4; 50.656 + case 9: 50.657 + return ST_MATRIX3; 50.658 + case 16: 50.659 + return ST_MATRIX4; 50.660 + default: 50.661 + break; 50.662 + } 50.663 + return ST_UNKNOWN; 50.664 +} 50.665 + 50.666 +static StType int_type(int elem) 50.667 +{ 50.668 + switch(elem) { 50.669 + case 1: 50.670 + return ST_INT; 50.671 + case 2: 50.672 + return ST_INT2; 50.673 + case 3: 50.674 + return ST_INT3; 50.675 + case 4: 50.676 + return ST_INT4; 50.677 + default: 50.678 + break; 50.679 + } 50.680 + return ST_UNKNOWN; 50.681 +}
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 51.2 +++ b/src/unistate.h Thu Nov 14 05:27:09 2013 +0200 51.3 @@ -0,0 +1,104 @@ 51.4 +#ifndef UNISTATE_H_ 51.5 +#define UNISTATE_H_ 51.6 + 51.7 +#include "vmath/vmath.h" 51.8 + 51.9 +class ShaderProg; 51.10 + 51.11 +enum StType { 51.12 + ST_UNKNOWN, 51.13 + ST_INT, ST_INT2, ST_INT3, ST_INT4, 51.14 + ST_FLOAT, ST_FLOAT2, ST_FLOAT3, ST_FLOAT4, 51.15 + ST_MATRIX3, ST_MATRIX4 51.16 +}; 51.17 + 51.18 +int add_unistate(const char *name, StType type); 51.19 +int get_unistate_index(const char *name); 51.20 + 51.21 +/** set the uniform state identified by \param sidx by copying 51.22 + * a number of elements from \param val. If \param count is 0 51.23 + * then it's automatically set based on the type of this state item. 51.24 + * @{ */ 51.25 +void set_unistate(int sidx, const int *val, int count = 0); 51.26 +void set_unistate(int sidx, const float *val, int count = 0); 51.27 +/// @} 51.28 + 51.29 +/** get the uniform state identified by \param sidx by copying 51.30 + * a number of elements into \param val. If \param count is 0 51.31 + * then it's automatically set based on the type of this state item. 51.32 + * @{ */ 51.33 +void get_unistate(int sidx, int *val, int count = 0); 51.34 +void get_unistate(int sidx, float *val, int count = 0); 51.35 +/// @} 51.36 + 51.37 +/// convenience versions of set_unistate @{ 51.38 +void set_unistate(int sidx, int val); 51.39 +void set_unistate(int sidx, float val); 51.40 +void set_unistate(int sidx, const Vector2 &vec); 51.41 +void set_unistate(int sidx, const Vector3 &vec); 51.42 +void set_unistate(int sidx, const Vector4 &vec); 51.43 +void set_unistate(int sidx, const Matrix3x3 &mat); 51.44 +void set_unistate(int sidx, const Matrix4x4 &mat); 51.45 +/// @} 51.46 + 51.47 +/** convenience functions for setting the uniform state by name. 51.48 + * if the name cannot be found in the current set of uniform state 51.49 + * items, a new one is created with a type derived from the variant 51.50 + * of the function that was called (which might not be what you want). 51.51 + * The index of the state item is returned. 51.52 + * @{ */ 51.53 +int set_unistate(const char *name, int *val, int count = 0); 51.54 +int set_unistate(const char *name, float *val, int count = 0); 51.55 +int set_unistate(const char *name, int val); 51.56 +int set_unistate(const char *name, float val); 51.57 +int set_unistate(const char *name, const Vector2 &vec); 51.58 +int set_unistate(const char *name, const Vector3 &vec); 51.59 +int set_unistate(const char *name, const Vector4 &vec); 51.60 +int set_unistate(const char *name, const Matrix3x3 &mat); 51.61 +int set_unistate(const char *name, const Matrix4x4 &mat); 51.62 +/// @} 51.63 + 51.64 +/// convenience versions of get_unistate @{ 51.65 +int get_unistate_int(int sidx); 51.66 +float get_unistate_float(int sidx); 51.67 +Vector2 get_unistate_vec2(int sidx); 51.68 +Vector3 get_unistate_vec3(int sidx); 51.69 +Vector4 get_unistate_vec4(int sidx); 51.70 +Matrix3x3 get_unistate_mat3(int sidx); 51.71 +Matrix4x4 get_unistate_mat4(int sidx); 51.72 +/// @} 51.73 + 51.74 +/// convenience versions of get_unistate for getting the uniform state by name @{ 51.75 +int get_unistate_int(const char *name); 51.76 +float get_unistate_float(const char *name); 51.77 +Vector2 get_unistate_vec2(const char *name); 51.78 +Vector3 get_unistate_vec3(const char *name); 51.79 +Vector4 get_unistate_vec4(const char *name); 51.80 +Matrix3x3 get_unistate_mat3(const char *name); 51.81 +Matrix4x4 get_unistate_mat4(const char *name); 51.82 +/// @} 51.83 + 51.84 +/** Prepare for rendering by setting up all the state uniforms in the shader sdr. 51.85 + * If sdr is null, then use the "current" shader as per ShaderProg::current 51.86 + */ 51.87 +void setup_unistate(const ShaderProg *sdr = 0); 51.88 + 51.89 +bool setup_unistate(int sidx, const ShaderProg *sdr, int loc); 51.90 +bool setup_unistate(const char *name, const ShaderProg *sdr); 51.91 + 51.92 +// special functions for setting the rendering pipeline matrices 51.93 +void set_world_matrix(const Matrix4x4 &mat); 51.94 +void set_view_matrix(const Matrix4x4 &mat); 51.95 +void set_projection_matrix(const Matrix4x4 &mat); 51.96 +void set_texture_matrix(const Matrix4x4 &mat); 51.97 + 51.98 +Matrix4x4 get_world_matrix(); 51.99 +Matrix4x4 get_view_matrix(); 51.100 +Matrix4x4 get_projection_matrix(); 51.101 +Matrix4x4 get_texture_matrix(); 51.102 + 51.103 +void setup_gl_matrices(); // this shouldn't be needed in the final code 51.104 + 51.105 +// TODO should do a matrix stack at some point ... 51.106 + 51.107 +#endif // UNISTATE_H_
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 52.2 +++ b/src/xform_node.cc Thu Nov 14 05:27:09 2013 +0200 52.3 @@ -0,0 +1,370 @@ 52.4 +#include <assert.h> 52.5 +#include <algorithm> 52.6 +#include "xform_node.h" 52.7 +#include "anim/anim.h" 52.8 +#include "anim/track.h" 52.9 + 52.10 +static inline anm_interpolator track_interpolator(Interp in); 52.11 +static inline anm_extrapolator track_extrapolator(Extrap ex); 52.12 + 52.13 +XFormNode::XFormNode() 52.14 +{ 52.15 + anm = new anm_node; 52.16 + anm_init_node(anm); 52.17 +} 52.18 + 52.19 +XFormNode::~XFormNode() 52.20 +{ 52.21 + anm_destroy_node(anm); 52.22 + delete anm; 52.23 +} 52.24 + 52.25 +void XFormNode::set_name(const char *name) 52.26 +{ 52.27 + anm_set_node_name(anm, name); 52.28 +} 52.29 + 52.30 +const char *XFormNode::get_name() const 52.31 +{ 52.32 + return anm_get_node_name(anm); 52.33 +} 52.34 + 52.35 +void XFormNode::set_interpolator(Interp in) 52.36 +{ 52.37 + anm_set_interpolator(anm, track_interpolator(in)); 52.38 + interp = in; 52.39 +} 52.40 + 52.41 +Interp XFormNode::get_interpolator() const 52.42 +{ 52.43 + return interp; 52.44 +} 52.45 + 52.46 +void XFormNode::set_extrapolator(Extrap ex) 52.47 +{ 52.48 + anm_set_extrapolator(anm, track_extrapolator(ex)); 52.49 + extrap = ex; 52.50 +} 52.51 + 52.52 +Extrap XFormNode::get_extrapolator() const 52.53 +{ 52.54 + return extrap; 52.55 +} 52.56 + 52.57 +void XFormNode::add_child(XFormNode *child) 52.58 +{ 52.59 + children.push_back(child); 52.60 + anm_link_node(anm, child->anm); 52.61 +} 52.62 + 52.63 +void XFormNode::remove_child(XFormNode *child) 52.64 +{ 52.65 + std::vector<XFormNode*>::iterator it; 52.66 + it = std::find(children.begin(), children.end(), child); 52.67 + if(it != children.end()) { 52.68 + children.erase(it); 52.69 + anm_unlink_node(anm, child->anm); 52.70 + } 52.71 +} 52.72 + 52.73 +int XFormNode::get_children_count() const 52.74 +{ 52.75 + return (int)children.size(); 52.76 +} 52.77 + 52.78 +XFormNode *XFormNode::get_child(int idx) 52.79 +{ 52.80 + if(idx >= 0 && idx < get_children_count()) { 52.81 + return children[idx]; 52.82 + } 52.83 + return 0; 52.84 +} 52.85 + 52.86 +const XFormNode *XFormNode::get_child(int idx) const 52.87 +{ 52.88 + if(idx >= 0 && idx < get_children_count()) { 52.89 + return children[idx]; 52.90 + } 52.91 + return 0; 52.92 +} 52.93 + 52.94 +void XFormNode::set_position(const Vector3 &pos, long tmsec) 52.95 +{ 52.96 + anm_set_position(anm, v3_cons(pos.x, pos.y, pos.z), ANM_MSEC2TM(tmsec)); 52.97 +} 52.98 + 52.99 +Vector3 XFormNode::get_node_position(long tmsec) const 52.100 +{ 52.101 + vec3_t p = anm_get_node_position(anm, ANM_MSEC2TM(tmsec)); 52.102 + return Vector3(p.x, p.y, p.z); 52.103 +} 52.104 + 52.105 +void XFormNode::set_rotation(const Quaternion &quat, long tmsec) 52.106 +{ 52.107 + anm_set_rotation(anm, quat_cons(quat.s, quat.v.x, quat.v.y, quat.v.z), ANM_MSEC2TM(tmsec)); 52.108 +} 52.109 + 52.110 +Quaternion XFormNode::get_node_rotation(long tmsec) const 52.111 +{ 52.112 + quat_t q = anm_get_node_rotation(anm, ANM_MSEC2TM(tmsec)); 52.113 + return Quaternion(q.w, q.x, q.y, q.z); 52.114 +} 52.115 + 52.116 +void XFormNode::set_scaling(const Vector3 &pos, long tmsec) 52.117 +{ 52.118 + anm_set_scaling(anm, v3_cons(pos.x, pos.y, pos.z), ANM_MSEC2TM(tmsec)); 52.119 +} 52.120 + 52.121 +Vector3 XFormNode::get_node_scaling(long tmsec) const 52.122 +{ 52.123 + vec3_t s = anm_get_node_scaling(anm, ANM_MSEC2TM(tmsec)); 52.124 + return Vector3(s.x, s.y, s.z); 52.125 +} 52.126 + 52.127 +// these take hierarchy into account 52.128 +Vector3 XFormNode::get_position(long tmsec) const 52.129 +{ 52.130 + vec3_t v = anm_get_position(anm, ANM_MSEC2TM(tmsec)); 52.131 + return Vector3(v.x, v.y, v.z); 52.132 +} 52.133 + 52.134 +Quaternion XFormNode::get_rotation(long tmsec) const 52.135 +{ 52.136 + quat_t q = anm_get_rotation(anm, tmsec); 52.137 + return Quaternion(q.w, q.x, q.y, q.z); 52.138 +} 52.139 + 52.140 +Vector3 XFormNode::get_scaling(long tmsec) const 52.141 +{ 52.142 + vec3_t v = anm_get_scaling(anm, ANM_MSEC2TM(tmsec)); 52.143 + return Vector3(v.x, v.y, v.z); 52.144 +} 52.145 + 52.146 +void XFormNode::set_pivot(const Vector3 &pivot) 52.147 +{ 52.148 + anm_set_pivot(anm, v3_cons(pivot.x, pivot.y, pivot.z)); 52.149 +} 52.150 + 52.151 +Vector3 XFormNode::get_pivot() const 52.152 +{ 52.153 + vec3_t p = anm_get_pivot(anm); 52.154 + return Vector3(p.x, p.y, p.z); 52.155 +} 52.156 + 52.157 +void XFormNode::set_local_matrix(const Matrix4x4 &mat) 52.158 +{ 52.159 + local_matrix = mat; 52.160 +} 52.161 + 52.162 +const Matrix4x4 &XFormNode::get_local_matrix() const 52.163 +{ 52.164 + return local_matrix; 52.165 +} 52.166 + 52.167 +void XFormNode::set_bone_matrix(const Matrix4x4 &bmat) 52.168 +{ 52.169 + bone_matrix = bmat; 52.170 +} 52.171 + 52.172 +const Matrix4x4 &XFormNode::get_bone_matrix() const 52.173 +{ 52.174 + return bone_matrix; 52.175 +} 52.176 + 52.177 +#define FOO 52.178 + 52.179 +void XFormNode::get_node_xform(long tmsec, Matrix4x4 *mat, Matrix4x4 *inv_mat) const 52.180 +{ 52.181 + anm_time_t tm = ANM_MSEC2TM(tmsec); 52.182 + 52.183 + if(mat) { 52.184 + anm_get_node_matrix(anm, (scalar_t(*)[4])mat, tm); 52.185 +#ifdef FOO 52.186 + *mat = local_matrix * *mat; 52.187 +#else 52.188 + *mat = *mat * local_matrix; 52.189 +#endif 52.190 + } 52.191 + if(inv_mat) { 52.192 + anm_get_inv_matrix(anm, (scalar_t(*)[4])inv_mat, tm); 52.193 + } 52.194 +} 52.195 + 52.196 +void XFormNode::get_xform(long tmsec, Matrix4x4 *mat, Matrix4x4 *inv_mat) const 52.197 +{ 52.198 + anm_time_t tm = ANM_MSEC2TM(tmsec); 52.199 + 52.200 + if(mat) { 52.201 + anm_get_matrix(anm, (scalar_t(*)[4])mat, tm); 52.202 +#ifdef FOO 52.203 + *mat = local_matrix * *mat; 52.204 +#else 52.205 + *mat = *mat * local_matrix; 52.206 +#endif 52.207 + } 52.208 + if(inv_mat) { 52.209 + anm_get_inv_matrix(anm, (scalar_t(*)[4])inv_mat, tm); 52.210 + } 52.211 +} 52.212 + 52.213 + 52.214 +// ---- Track ---- 52.215 + 52.216 +Track::Track() 52.217 +{ 52.218 + trk = new anm_track; 52.219 + anm_init_track(trk); 52.220 +} 52.221 + 52.222 +Track::~Track() 52.223 +{ 52.224 + anm_destroy_track(trk); 52.225 + delete trk; 52.226 +} 52.227 + 52.228 +Track::Track(const Track &rhs) 52.229 +{ 52.230 + trk = new anm_track; 52.231 + anm_init_track(trk); 52.232 + anm_copy_track(trk, rhs.trk); 52.233 + interp = rhs.interp; 52.234 + extrap = rhs.extrap; 52.235 +} 52.236 + 52.237 +Track &Track::operator =(const Track &rhs) 52.238 +{ 52.239 + if(&rhs == this) { 52.240 + return *this; 52.241 + } 52.242 + 52.243 + anm_copy_track(trk, rhs.trk); 52.244 + interp = rhs.interp; 52.245 + extrap = rhs.extrap; 52.246 + return *this; 52.247 +} 52.248 + 52.249 + 52.250 +void Track::set_interpolator(Interp in) 52.251 +{ 52.252 + anm_set_track_interpolator(trk, track_interpolator(in)); 52.253 + interp = in; 52.254 +} 52.255 + 52.256 +Interp Track::get_interpolator() const 52.257 +{ 52.258 + return interp; 52.259 +} 52.260 + 52.261 +void Track::set_extrapolator(Extrap ex) 52.262 +{ 52.263 + anm_set_track_extrapolator(trk, track_extrapolator(ex)); 52.264 + extrap = ex; 52.265 +} 52.266 + 52.267 +Extrap Track::get_extrapolator() const 52.268 +{ 52.269 + return extrap; 52.270 +} 52.271 + 52.272 +void Track::set_default(double def) 52.273 +{ 52.274 + anm_set_track_default(trk, def); 52.275 +} 52.276 + 52.277 +void Track::set_value(float val, long tmsec) 52.278 +{ 52.279 + anm_set_value(trk, ANM_MSEC2TM(tmsec), val); 52.280 +} 52.281 + 52.282 +float Track::get_value(long tmsec) const 52.283 +{ 52.284 + return anm_get_value(trk, ANM_MSEC2TM(tmsec)); 52.285 +} 52.286 + 52.287 +float Track::operator ()(long tmsec) const 52.288 +{ 52.289 + return anm_get_value(trk, ANM_MSEC2TM(tmsec)); 52.290 +} 52.291 + 52.292 + 52.293 +// ---- Track3 ---- 52.294 + 52.295 +void Track3::set_interpolator(Interp in) 52.296 +{ 52.297 + for(int i=0; i<3; i++) { 52.298 + track[i].set_interpolator(in); 52.299 + } 52.300 +} 52.301 + 52.302 +Interp Track3::get_interpolator() const 52.303 +{ 52.304 + return track[0].get_interpolator(); 52.305 +} 52.306 + 52.307 +void Track3::set_extrapolator(Extrap ex) 52.308 +{ 52.309 + for(int i=0; i<3; i++) { 52.310 + track[i].set_extrapolator(ex); 52.311 + } 52.312 +} 52.313 + 52.314 +Extrap Track3::get_extrapolator() const 52.315 +{ 52.316 + return track[0].get_extrapolator(); 52.317 +} 52.318 + 52.319 +void Track3::set_default(const Vector3 &def) 52.320 +{ 52.321 + for(int i=0; i<3; i++) { 52.322 + track[i].set_default(def[i]); 52.323 + } 52.324 +} 52.325 + 52.326 +void Track3::set_value(const Vector3 &val, long tmsec) 52.327 +{ 52.328 + for(int i=0; i<3; i++) { 52.329 + track[i].set_value(val[i], tmsec); 52.330 + } 52.331 +} 52.332 + 52.333 +Vector3 Track3::get_value(long tmsec) const 52.334 +{ 52.335 + return Vector3(track[0](tmsec), track[1](tmsec), track[2](tmsec)); 52.336 +} 52.337 + 52.338 +Vector3 Track3::operator ()(long tmsec) const 52.339 +{ 52.340 + return Vector3(track[0](tmsec), track[1](tmsec), track[2](tmsec)); 52.341 +} 52.342 + 52.343 + 52.344 +static inline anm_interpolator track_interpolator(Interp in) 52.345 +{ 52.346 + switch(in) { 52.347 + case INTERP_STEP: 52.348 + return ANM_INTERP_STEP; 52.349 + case INTERP_LINEAR: 52.350 + return ANM_INTERP_LINEAR; 52.351 + case INTERP_CUBIC: 52.352 + return ANM_INTERP_CUBIC; 52.353 + } 52.354 + 52.355 + assert(0); 52.356 + return ANM_INTERP_STEP; 52.357 +} 52.358 + 52.359 +static inline anm_extrapolator track_extrapolator(Extrap ex) 52.360 +{ 52.361 + switch(ex) { 52.362 + case EXTRAP_EXTEND: 52.363 + return ANM_EXTRAP_EXTEND; 52.364 + case EXTRAP_CLAMP: 52.365 + return ANM_EXTRAP_CLAMP; 52.366 + case EXTRAP_REPEAT: 52.367 + return ANM_EXTRAP_REPEAT; 52.368 + } 52.369 + 52.370 + assert(0); 52.371 + return ANM_EXTRAP_EXTEND; 52.372 +} 52.373 +
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 53.2 +++ b/src/xform_node.h Thu Nov 14 05:27:09 2013 +0200 53.3 @@ -0,0 +1,134 @@ 53.4 +/* 53.5 +TODO: add multiple animations per node in libanim (i.e. multiple sets of tracks) 53.6 +*/ 53.7 +#ifndef XFORM_NODE_H_ 53.8 +#define XFORM_NODE_H_ 53.9 + 53.10 +#include <vector> 53.11 +#include "vmath/vector.h" 53.12 +#include "vmath/quat.h" 53.13 +#include "vmath/matrix.h" 53.14 + 53.15 +enum Interp { INTERP_STEP, INTERP_LINEAR, INTERP_CUBIC }; 53.16 +enum Extrap { EXTRAP_EXTEND, EXTRAP_CLAMP, EXTRAP_REPEAT }; 53.17 + 53.18 +struct anm_node; 53.19 +struct anm_track; 53.20 + 53.21 +// XXX all time arguments are milliseconds 53.22 + 53.23 +class XFormNode { 53.24 +private: 53.25 + struct anm_node *anm; 53.26 + std::vector<XFormNode*> children; 53.27 + 53.28 + Interp interp; 53.29 + Extrap extrap; 53.30 + 53.31 + Matrix4x4 local_matrix; 53.32 + Matrix4x4 bone_matrix; 53.33 + 53.34 + XFormNode(const XFormNode &node) {} 53.35 + XFormNode &operator =(const XFormNode &node) { return *this; } 53.36 + 53.37 +public: 53.38 + XFormNode(); 53.39 + virtual ~XFormNode(); 53.40 + 53.41 + void set_name(const char *name); 53.42 + const char *get_name() const; 53.43 + 53.44 + void set_interpolator(Interp in); 53.45 + Interp get_interpolator() const; 53.46 + void set_extrapolator(Extrap ex); 53.47 + Extrap get_extrapolator() const; 53.48 + 53.49 + // children management 53.50 + void add_child(XFormNode *child); 53.51 + void remove_child(XFormNode *child); 53.52 + 53.53 + int get_children_count() const; 53.54 + XFormNode *get_child(int idx); 53.55 + const XFormNode *get_child(int idx) const; 53.56 + 53.57 + 53.58 + void set_position(const Vector3 &pos, long tmsec = 0); 53.59 + Vector3 get_node_position(long tmsec = 0) const; 53.60 + 53.61 + void set_rotation(const Quaternion &quat, long tmsec = 0); 53.62 + Quaternion get_node_rotation(long tmsec = 0) const; 53.63 + 53.64 + void set_scaling(const Vector3 &pos, long tmsec = 0); 53.65 + Vector3 get_node_scaling(long tmsec = 0) const; 53.66 + 53.67 + // these take hierarchy into account 53.68 + Vector3 get_position(long tmsec = 0) const; 53.69 + Quaternion get_rotation(long tmsec = 0) const; 53.70 + Vector3 get_scaling(long tmsec = 0) const; 53.71 + 53.72 + void set_pivot(const Vector3 &pivot); 53.73 + Vector3 get_pivot() const; 53.74 + 53.75 + // the local matrix is concatenated with the regular node/anim matrix 53.76 + void set_local_matrix(const Matrix4x4 &mat); 53.77 + const Matrix4x4 &get_local_matrix() const; 53.78 + 53.79 + // for bone nodes, the transformation of the bone in bind position 53.80 + void set_bone_matrix(const Matrix4x4 &bmat); 53.81 + const Matrix4x4 &get_bone_matrix() const; 53.82 + 53.83 + // node transformation alone 53.84 + void get_node_xform(long tmsec, Matrix4x4 *mat, Matrix4x4 *inv_mat = 0) const; 53.85 + 53.86 + // node transformation taking hierarchy into account 53.87 + void get_xform(long tmsec, Matrix4x4 *mat, Matrix4x4 *inv_mat = 0) const; 53.88 +}; 53.89 + 53.90 + 53.91 +class Track { 53.92 +private: 53.93 + struct anm_track *trk; 53.94 + Interp interp; 53.95 + Extrap extrap; 53.96 + 53.97 +public: 53.98 + Track(); 53.99 + ~Track(); 53.100 + 53.101 + Track(const Track &trk); 53.102 + Track &operator =(const Track &trk); 53.103 + 53.104 + void set_interpolator(Interp in); 53.105 + Interp get_interpolator() const; 53.106 + void set_extrapolator(Extrap ex); 53.107 + Extrap get_extrapolator() const; 53.108 + 53.109 + void set_default(double def); 53.110 + 53.111 + void set_value(float val, long tmsec = 0); 53.112 + float get_value(long tmsec = 0) const; 53.113 + 53.114 + // the same as get_value 53.115 + float operator ()(long tmsec = 0) const; 53.116 +}; 53.117 + 53.118 +class Track3 { 53.119 +private: 53.120 + Track track[3]; 53.121 + 53.122 +public: 53.123 + void set_interpolator(Interp in); 53.124 + Interp get_interpolator() const; 53.125 + void set_extrapolator(Extrap ex); 53.126 + Extrap get_extrapolator() const; 53.127 + 53.128 + void set_default(const Vector3 &def); 53.129 + 53.130 + void set_value(const Vector3 &val, long tmsec = 0); 53.131 + Vector3 get_value(long tmsec = 0) const; 53.132 + 53.133 + // the same as get_value 53.134 + Vector3 operator ()(long tmsec = 0) const; 53.135 +}; 53.136 + 53.137 +#endif /* XFORM_NODE_H_ */