diff options
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/CAnimatedMeshHalfLife.cpp')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/CAnimatedMeshHalfLife.cpp | 3390 |
1 files changed, 1695 insertions, 1695 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CAnimatedMeshHalfLife.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CAnimatedMeshHalfLife.cpp index 6531e1a..ea81c59 100644 --- a/libraries/irrlicht-1.8/source/Irrlicht/CAnimatedMeshHalfLife.cpp +++ b/libraries/irrlicht-1.8/source/Irrlicht/CAnimatedMeshHalfLife.cpp | |||
@@ -1,1695 +1,1695 @@ | |||
1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt / Fabio Concas / Thomas Alten | 1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt / Fabio Concas / Thomas Alten |
2 | // This file is part of the "Irrlicht Engine". | 2 | // This file is part of the "Irrlicht Engine". |
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h | 3 | // For conditions of distribution and use, see copyright notice in irrlicht.h |
4 | 4 | ||
5 | #include "IrrCompileConfig.h" | 5 | #include "IrrCompileConfig.h" |
6 | #ifdef _IRR_COMPILE_WITH_HALFLIFE_LOADER_ | 6 | #ifdef _IRR_COMPILE_WITH_HALFLIFE_LOADER_ |
7 | 7 | ||
8 | #include "CAnimatedMeshHalfLife.h" | 8 | #include "CAnimatedMeshHalfLife.h" |
9 | #include "os.h" | 9 | #include "os.h" |
10 | #include "CColorConverter.h" | 10 | #include "CColorConverter.h" |
11 | #include "CImage.h" | 11 | #include "CImage.h" |
12 | #include "coreutil.h" | 12 | #include "coreutil.h" |
13 | #include "SMeshBuffer.h" | 13 | #include "SMeshBuffer.h" |
14 | #include "IVideoDriver.h" | 14 | #include "IVideoDriver.h" |
15 | #include "IFileSystem.h" | 15 | #include "IFileSystem.h" |
16 | 16 | ||
17 | namespace irr | 17 | namespace irr |
18 | { | 18 | { |
19 | namespace scene | 19 | namespace scene |
20 | { | 20 | { |
21 | 21 | ||
22 | using namespace video; | 22 | using namespace video; |
23 | 23 | ||
24 | void AngleQuaternion(const core::vector3df& angles, vec4_hl quaternion) | 24 | void AngleQuaternion(const core::vector3df& angles, vec4_hl quaternion) |
25 | { | 25 | { |
26 | f32 angle; | 26 | f32 angle; |
27 | f32 sr, sp, sy, cr, cp, cy; | 27 | f32 sr, sp, sy, cr, cp, cy; |
28 | 28 | ||
29 | // FIXME: rescale the inputs to 1/2 angle | 29 | // FIXME: rescale the inputs to 1/2 angle |
30 | angle = angles.Z * 0.5f; | 30 | angle = angles.Z * 0.5f; |
31 | sy = sin(angle); | 31 | sy = sin(angle); |
32 | cy = cos(angle); | 32 | cy = cos(angle); |
33 | angle = angles.Y * 0.5f; | 33 | angle = angles.Y * 0.5f; |
34 | sp = sin(angle); | 34 | sp = sin(angle); |
35 | cp = cos(angle); | 35 | cp = cos(angle); |
36 | angle = angles.X * 0.5f; | 36 | angle = angles.X * 0.5f; |
37 | sr = sin(angle); | 37 | sr = sin(angle); |
38 | cr = cos(angle); | 38 | cr = cos(angle); |
39 | 39 | ||
40 | quaternion[0] = sr*cp*cy-cr*sp*sy; // X | 40 | quaternion[0] = sr*cp*cy-cr*sp*sy; // X |
41 | quaternion[1] = cr*sp*cy+sr*cp*sy; // Y | 41 | quaternion[1] = cr*sp*cy+sr*cp*sy; // Y |
42 | quaternion[2] = cr*cp*sy-sr*sp*cy; // Z | 42 | quaternion[2] = cr*cp*sy-sr*sp*cy; // Z |
43 | quaternion[3] = cr*cp*cy+sr*sp*sy; // W | 43 | quaternion[3] = cr*cp*cy+sr*sp*sy; // W |
44 | } | 44 | } |
45 | 45 | ||
46 | void QuaternionMatrix( const vec4_hl quaternion, f32 (*matrix)[4] ) | 46 | void QuaternionMatrix( const vec4_hl quaternion, f32 (*matrix)[4] ) |
47 | { | 47 | { |
48 | matrix[0][0] = 1.f - 2.f * quaternion[1] * quaternion[1] - 2.f * quaternion[2] * quaternion[2]; | 48 | matrix[0][0] = 1.f - 2.f * quaternion[1] * quaternion[1] - 2.f * quaternion[2] * quaternion[2]; |
49 | matrix[1][0] = 2.f * quaternion[0] * quaternion[1] + 2.f * quaternion[3] * quaternion[2]; | 49 | matrix[1][0] = 2.f * quaternion[0] * quaternion[1] + 2.f * quaternion[3] * quaternion[2]; |
50 | matrix[2][0] = 2.f * quaternion[0] * quaternion[2] - 2.f * quaternion[3] * quaternion[1]; | 50 | matrix[2][0] = 2.f * quaternion[0] * quaternion[2] - 2.f * quaternion[3] * quaternion[1]; |
51 | 51 | ||
52 | matrix[0][1] = 2.f * quaternion[0] * quaternion[1] - 2.f * quaternion[3] * quaternion[2]; | 52 | matrix[0][1] = 2.f * quaternion[0] * quaternion[1] - 2.f * quaternion[3] * quaternion[2]; |
53 | matrix[1][1] = 1.f - 2.f * quaternion[0] * quaternion[0] - 2.f * quaternion[2] * quaternion[2]; | 53 | matrix[1][1] = 1.f - 2.f * quaternion[0] * quaternion[0] - 2.f * quaternion[2] * quaternion[2]; |
54 | matrix[2][1] = 2.f * quaternion[1] * quaternion[2] + 2.f * quaternion[3] * quaternion[0]; | 54 | matrix[2][1] = 2.f * quaternion[1] * quaternion[2] + 2.f * quaternion[3] * quaternion[0]; |
55 | 55 | ||
56 | matrix[0][2] = 2.f * quaternion[0] * quaternion[2] + 2.f * quaternion[3] * quaternion[1]; | 56 | matrix[0][2] = 2.f * quaternion[0] * quaternion[2] + 2.f * quaternion[3] * quaternion[1]; |
57 | matrix[1][2] = 2.f * quaternion[1] * quaternion[2] - 2.f * quaternion[3] * quaternion[0]; | 57 | matrix[1][2] = 2.f * quaternion[1] * quaternion[2] - 2.f * quaternion[3] * quaternion[0]; |
58 | matrix[2][2] = 1.f - 2.f * quaternion[0] * quaternion[0] - 2.f * quaternion[1] * quaternion[1]; | 58 | matrix[2][2] = 1.f - 2.f * quaternion[0] * quaternion[0] - 2.f * quaternion[1] * quaternion[1]; |
59 | } | 59 | } |
60 | 60 | ||
61 | void QuaternionSlerp( const vec4_hl p, vec4_hl q, f32 t, vec4_hl qt ) | 61 | void QuaternionSlerp( const vec4_hl p, vec4_hl q, f32 t, vec4_hl qt ) |
62 | { | 62 | { |
63 | s32 i; | 63 | s32 i; |
64 | f32 omega, cosom, sinom, sclp, sclq; | 64 | f32 omega, cosom, sinom, sclp, sclq; |
65 | 65 | ||
66 | // decide if one of the quaternions is backwards | 66 | // decide if one of the quaternions is backwards |
67 | f32 a = 0; | 67 | f32 a = 0; |
68 | f32 b = 0; | 68 | f32 b = 0; |
69 | for (i = 0; i < 4; i++) { | 69 | for (i = 0; i < 4; i++) { |
70 | a += (p[i]-q[i])*(p[i]-q[i]); | 70 | a += (p[i]-q[i])*(p[i]-q[i]); |
71 | b += (p[i]+q[i])*(p[i]+q[i]); | 71 | b += (p[i]+q[i])*(p[i]+q[i]); |
72 | } | 72 | } |
73 | if (a > b) { | 73 | if (a > b) { |
74 | for (i = 0; i < 4; i++) { | 74 | for (i = 0; i < 4; i++) { |
75 | q[i] = -q[i]; | 75 | q[i] = -q[i]; |
76 | } | 76 | } |
77 | } | 77 | } |
78 | 78 | ||
79 | cosom = p[0]*q[0] + p[1]*q[1] + p[2]*q[2] + p[3]*q[3]; | 79 | cosom = p[0]*q[0] + p[1]*q[1] + p[2]*q[2] + p[3]*q[3]; |
80 | 80 | ||
81 | if ((1.f + cosom) > 0.00000001) { | 81 | if ((1.f + cosom) > 0.00000001) { |
82 | if ((1.f - cosom) > 0.00000001) { | 82 | if ((1.f - cosom) > 0.00000001) { |
83 | omega = acos( cosom ); | 83 | omega = acos( cosom ); |
84 | sinom = sin( omega ); | 84 | sinom = sin( omega ); |
85 | sclp = sin( (1.f - t)*omega) / sinom; | 85 | sclp = sin( (1.f - t)*omega) / sinom; |
86 | sclq = sin( t*omega ) / sinom; | 86 | sclq = sin( t*omega ) / sinom; |
87 | } | 87 | } |
88 | else { | 88 | else { |
89 | sclp = 1.f - t; | 89 | sclp = 1.f - t; |
90 | sclq = t; | 90 | sclq = t; |
91 | } | 91 | } |
92 | for (i = 0; i < 4; i++) { | 92 | for (i = 0; i < 4; i++) { |
93 | qt[i] = sclp * p[i] + sclq * q[i]; | 93 | qt[i] = sclp * p[i] + sclq * q[i]; |
94 | } | 94 | } |
95 | } | 95 | } |
96 | else { | 96 | else { |
97 | qt[0] = -p[1]; | 97 | qt[0] = -p[1]; |
98 | qt[1] = p[0]; | 98 | qt[1] = p[0]; |
99 | qt[2] = -p[3]; | 99 | qt[2] = -p[3]; |
100 | qt[3] = p[2]; | 100 | qt[3] = p[2]; |
101 | sclp = sin( (1.f - t) * 0.5f * core::PI); | 101 | sclp = sin( (1.f - t) * 0.5f * core::PI); |
102 | sclq = sin( t * 0.5f * core::PI); | 102 | sclq = sin( t * 0.5f * core::PI); |
103 | for (i = 0; i < 3; i++) { | 103 | for (i = 0; i < 3; i++) { |
104 | qt[i] = sclp * p[i] + sclq * qt[i]; | 104 | qt[i] = sclp * p[i] + sclq * qt[i]; |
105 | } | 105 | } |
106 | } | 106 | } |
107 | } | 107 | } |
108 | 108 | ||
109 | void R_ConcatTransforms (const f32 in1[3][4], const f32 in2[3][4], f32 out[3][4]) | 109 | void R_ConcatTransforms (const f32 in1[3][4], const f32 in2[3][4], f32 out[3][4]) |
110 | { | 110 | { |
111 | out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0]; | 111 | out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0]; |
112 | out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1]; | 112 | out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1]; |
113 | out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2]; | 113 | out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2]; |
114 | out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][2] * in2[2][3] + in1[0][3]; | 114 | out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][2] * in2[2][3] + in1[0][3]; |
115 | out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0]; | 115 | out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0]; |
116 | out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1]; | 116 | out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1]; |
117 | out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2]; | 117 | out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2]; |
118 | out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][2] * in2[2][3] + in1[1][3]; | 118 | out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][2] * in2[2][3] + in1[1][3]; |
119 | out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0]; | 119 | out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0]; |
120 | out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1]; | 120 | out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1]; |
121 | out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2]; | 121 | out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2]; |
122 | out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3]; | 122 | out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3]; |
123 | } | 123 | } |
124 | 124 | ||
125 | #define DotProduct(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]) | 125 | #define DotProduct(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]) |
126 | 126 | ||
127 | inline void VectorTransform(const vec3_hl in1, const f32 in2[3][4], core::vector3df& out) | 127 | inline void VectorTransform(const vec3_hl in1, const f32 in2[3][4], core::vector3df& out) |
128 | { | 128 | { |
129 | out.X = DotProduct(in1, in2[0]) + in2[0][3]; | 129 | out.X = DotProduct(in1, in2[0]) + in2[0][3]; |
130 | out.Z = DotProduct(in1, in2[1]) + in2[1][3]; | 130 | out.Z = DotProduct(in1, in2[1]) + in2[1][3]; |
131 | out.Y = DotProduct(in1, in2[2]) + in2[2][3]; | 131 | out.Y = DotProduct(in1, in2[2]) + in2[2][3]; |
132 | } | 132 | } |
133 | 133 | ||
134 | static f32 BoneTransform[MAXSTUDIOBONES][3][4]; // bone transformation matrix | 134 | static f32 BoneTransform[MAXSTUDIOBONES][3][4]; // bone transformation matrix |
135 | 135 | ||
136 | void getBoneVector ( core::vector3df &out, u32 index ) | 136 | void getBoneVector ( core::vector3df &out, u32 index ) |
137 | { | 137 | { |
138 | out.X = BoneTransform[index][0][3]; | 138 | out.X = BoneTransform[index][0][3]; |
139 | out.Z = BoneTransform[index][1][3]; | 139 | out.Z = BoneTransform[index][1][3]; |
140 | out.Y = BoneTransform[index][2][3]; | 140 | out.Y = BoneTransform[index][2][3]; |
141 | } | 141 | } |
142 | 142 | ||
143 | void getBoneBox ( core::aabbox3df &box, u32 index, f32 size = 0.5f ) | 143 | void getBoneBox ( core::aabbox3df &box, u32 index, f32 size = 0.5f ) |
144 | { | 144 | { |
145 | box.MinEdge.X = BoneTransform[index][0][3] - size; | 145 | box.MinEdge.X = BoneTransform[index][0][3] - size; |
146 | box.MinEdge.Z = BoneTransform[index][1][3] - size; | 146 | box.MinEdge.Z = BoneTransform[index][1][3] - size; |
147 | box.MinEdge.Y = BoneTransform[index][2][3] - size; | 147 | box.MinEdge.Y = BoneTransform[index][2][3] - size; |
148 | 148 | ||
149 | size *= 2.f; | 149 | size *= 2.f; |
150 | box.MaxEdge.X = box.MinEdge.X + size; | 150 | box.MaxEdge.X = box.MinEdge.X + size; |
151 | box.MaxEdge.Y = box.MinEdge.Y + size; | 151 | box.MaxEdge.Y = box.MinEdge.Y + size; |
152 | box.MaxEdge.Z = box.MinEdge.Z + size; | 152 | box.MaxEdge.Z = box.MinEdge.Z + size; |
153 | } | 153 | } |
154 | 154 | ||
155 | void getTransformedBoneVector ( core::vector3df &out, u32 index, const vec3_hl in) | 155 | void getTransformedBoneVector ( core::vector3df &out, u32 index, const vec3_hl in) |
156 | { | 156 | { |
157 | out.X = DotProduct(in, BoneTransform[index][0]) + BoneTransform[index][0][3]; | 157 | out.X = DotProduct(in, BoneTransform[index][0]) + BoneTransform[index][0][3]; |
158 | out.Z = DotProduct(in, BoneTransform[index][1]) + BoneTransform[index][1][3]; | 158 | out.Z = DotProduct(in, BoneTransform[index][1]) + BoneTransform[index][1][3]; |
159 | out.Y = DotProduct(in, BoneTransform[index][2]) + BoneTransform[index][2][3]; | 159 | out.Y = DotProduct(in, BoneTransform[index][2]) + BoneTransform[index][2][3]; |
160 | 160 | ||
161 | } | 161 | } |
162 | 162 | ||
163 | 163 | ||
164 | //! Constructor | 164 | //! Constructor |
165 | CHalflifeMDLMeshFileLoader::CHalflifeMDLMeshFileLoader( | 165 | CHalflifeMDLMeshFileLoader::CHalflifeMDLMeshFileLoader( |
166 | scene::ISceneManager* smgr) : SceneManager(smgr) | 166 | scene::ISceneManager* smgr) : SceneManager(smgr) |
167 | { | 167 | { |
168 | #ifdef _DEBUG | 168 | #ifdef _DEBUG |
169 | setDebugName("CHalflifeMDLMeshFileLoader"); | 169 | setDebugName("CHalflifeMDLMeshFileLoader"); |
170 | #endif | 170 | #endif |
171 | } | 171 | } |
172 | 172 | ||
173 | 173 | ||
174 | //! returns true if the file maybe is able to be loaded by this class | 174 | //! returns true if the file maybe is able to be loaded by this class |
175 | //! based on the file extension (e.g. ".bsp") | 175 | //! based on the file extension (e.g. ".bsp") |
176 | bool CHalflifeMDLMeshFileLoader::isALoadableFileExtension(const io::path& filename) const | 176 | bool CHalflifeMDLMeshFileLoader::isALoadableFileExtension(const io::path& filename) const |
177 | { | 177 | { |
178 | return core::hasFileExtension(filename, "mdl"); | 178 | return core::hasFileExtension(filename, "mdl"); |
179 | } | 179 | } |
180 | 180 | ||
181 | 181 | ||
182 | //! creates/loads an animated mesh from the file. | 182 | //! creates/loads an animated mesh from the file. |
183 | //! \return Pointer to the created mesh. Returns 0 if loading failed. | 183 | //! \return Pointer to the created mesh. Returns 0 if loading failed. |
184 | //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). | 184 | //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). |
185 | //! See IReferenceCounted::drop() for more information. | 185 | //! See IReferenceCounted::drop() for more information. |
186 | IAnimatedMesh* CHalflifeMDLMeshFileLoader::createMesh(io::IReadFile* file) | 186 | IAnimatedMesh* CHalflifeMDLMeshFileLoader::createMesh(io::IReadFile* file) |
187 | { | 187 | { |
188 | CAnimatedMeshHalfLife* msh = new CAnimatedMeshHalfLife(); | 188 | CAnimatedMeshHalfLife* msh = new CAnimatedMeshHalfLife(); |
189 | if (msh) | 189 | if (msh) |
190 | { | 190 | { |
191 | if (msh->loadModelFile(file, SceneManager)) | 191 | if (msh->loadModelFile(file, SceneManager)) |
192 | return msh; | 192 | return msh; |
193 | msh->drop(); | 193 | msh->drop(); |
194 | } | 194 | } |
195 | 195 | ||
196 | return 0; | 196 | return 0; |
197 | } | 197 | } |
198 | 198 | ||
199 | 199 | ||
200 | //! Constructor | 200 | //! Constructor |
201 | CAnimatedMeshHalfLife::CAnimatedMeshHalfLife() | 201 | CAnimatedMeshHalfLife::CAnimatedMeshHalfLife() |
202 | : FrameCount(0), MeshIPol(0), SceneManager(0), Header(0), TextureHeader(0), | 202 | : FrameCount(0), MeshIPol(0), SceneManager(0), Header(0), TextureHeader(0), |
203 | OwnTexModel(false), SequenceIndex(0), CurrentFrame(0), FramesPerSecond(25.f), | 203 | OwnTexModel(false), SequenceIndex(0), CurrentFrame(0), FramesPerSecond(25.f), |
204 | SkinGroupSelection(0) | 204 | SkinGroupSelection(0) |
205 | #ifdef HL_TEXTURE_ATLAS | 205 | #ifdef HL_TEXTURE_ATLAS |
206 | , TextureMaster(0) | 206 | , TextureMaster(0) |
207 | #endif | 207 | #endif |
208 | { | 208 | { |
209 | #ifdef _DEBUG | 209 | #ifdef _DEBUG |
210 | setDebugName("CAnimatedMeshHalfLife"); | 210 | setDebugName("CAnimatedMeshHalfLife"); |
211 | #endif | 211 | #endif |
212 | initData(); | 212 | initData(); |
213 | } | 213 | } |
214 | 214 | ||
215 | /*! | 215 | /*! |
216 | loads a complete model | 216 | loads a complete model |
217 | */ | 217 | */ |
218 | bool CAnimatedMeshHalfLife::loadModelFile(io::IReadFile* file, | 218 | bool CAnimatedMeshHalfLife::loadModelFile(io::IReadFile* file, |
219 | ISceneManager* smgr) | 219 | ISceneManager* smgr) |
220 | { | 220 | { |
221 | if (!file) | 221 | if (!file) |
222 | return false; | 222 | return false; |
223 | 223 | ||
224 | SceneManager = smgr; | 224 | SceneManager = smgr; |
225 | 225 | ||
226 | if ( loadModel(file, file->getFileName()) ) | 226 | if ( loadModel(file, file->getFileName()) ) |
227 | { | 227 | { |
228 | if ( postLoadModel ( file->getFileName() ) ) | 228 | if ( postLoadModel ( file->getFileName() ) ) |
229 | { | 229 | { |
230 | initModel (); | 230 | initModel (); |
231 | //dumpModelInfo ( 1 ); | 231 | //dumpModelInfo ( 1 ); |
232 | return true; | 232 | return true; |
233 | } | 233 | } |
234 | } | 234 | } |
235 | return false; | 235 | return false; |
236 | } | 236 | } |
237 | 237 | ||
238 | 238 | ||
239 | //! Destructor | 239 | //! Destructor |
240 | CAnimatedMeshHalfLife::~CAnimatedMeshHalfLife() | 240 | CAnimatedMeshHalfLife::~CAnimatedMeshHalfLife() |
241 | { | 241 | { |
242 | delete [] (u8*) Header; | 242 | delete [] (u8*) Header; |
243 | if (OwnTexModel) | 243 | if (OwnTexModel) |
244 | delete [] (u8*) TextureHeader; | 244 | delete [] (u8*) TextureHeader; |
245 | 245 | ||
246 | for (u32 i = 0; i < 32; ++i) | 246 | for (u32 i = 0; i < 32; ++i) |
247 | delete [] (u8*) AnimationHeader[i]; | 247 | delete [] (u8*) AnimationHeader[i]; |
248 | 248 | ||
249 | if (MeshIPol) | 249 | if (MeshIPol) |
250 | MeshIPol->drop(); | 250 | MeshIPol->drop(); |
251 | } | 251 | } |
252 | 252 | ||
253 | 253 | ||
254 | //! Returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh. | 254 | //! Returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh. |
255 | u32 CAnimatedMeshHalfLife::getFrameCount() const | 255 | u32 CAnimatedMeshHalfLife::getFrameCount() const |
256 | { | 256 | { |
257 | return FrameCount; | 257 | return FrameCount; |
258 | } | 258 | } |
259 | 259 | ||
260 | 260 | ||
261 | //! set the hardware mapping hint, for driver | 261 | //! set the hardware mapping hint, for driver |
262 | void CAnimatedMeshHalfLife::setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint,E_BUFFER_TYPE buffer) | 262 | void CAnimatedMeshHalfLife::setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint,E_BUFFER_TYPE buffer) |
263 | { | 263 | { |
264 | } | 264 | } |
265 | 265 | ||
266 | 266 | ||
267 | //! flags the meshbuffer as changed, reloads hardware buffers | 267 | //! flags the meshbuffer as changed, reloads hardware buffers |
268 | void CAnimatedMeshHalfLife::setDirty(E_BUFFER_TYPE buffer) | 268 | void CAnimatedMeshHalfLife::setDirty(E_BUFFER_TYPE buffer) |
269 | { | 269 | { |
270 | } | 270 | } |
271 | 271 | ||
272 | 272 | ||
273 | static core::vector3df TransformedVerts[MAXSTUDIOVERTS]; // transformed vertices | 273 | static core::vector3df TransformedVerts[MAXSTUDIOVERTS]; // transformed vertices |
274 | //static core::vector3df TransformedNormals[MAXSTUDIOVERTS]; // light surface normals | 274 | //static core::vector3df TransformedNormals[MAXSTUDIOVERTS]; // light surface normals |
275 | 275 | ||
276 | 276 | ||
277 | /*! | 277 | /*! |
278 | */ | 278 | */ |
279 | void CAnimatedMeshHalfLife::initModel() | 279 | void CAnimatedMeshHalfLife::initModel() |
280 | { | 280 | { |
281 | // init Sequences to Animation | 281 | // init Sequences to Animation |
282 | KeyFrameInterpolation ipol; | 282 | KeyFrameInterpolation ipol; |
283 | ipol.Name.reserve ( 64 ); | 283 | ipol.Name.reserve ( 64 ); |
284 | u32 i; | 284 | u32 i; |
285 | 285 | ||
286 | AnimList.clear(); | 286 | AnimList.clear(); |
287 | FrameCount = 0; | 287 | FrameCount = 0; |
288 | 288 | ||
289 | SHalflifeSequence *seq = (SHalflifeSequence*) ((u8*) Header + Header->seqindex); | 289 | SHalflifeSequence *seq = (SHalflifeSequence*) ((u8*) Header + Header->seqindex); |
290 | for ( i = 0; i < Header->numseq; i++) | 290 | for ( i = 0; i < Header->numseq; i++) |
291 | { | 291 | { |
292 | ipol.Name = seq[i].label; | 292 | ipol.Name = seq[i].label; |
293 | ipol.StartFrame = FrameCount; | 293 | ipol.StartFrame = FrameCount; |
294 | ipol.Frames = core::max_ ( 1, seq[i].numframes - 1 ); | 294 | ipol.Frames = core::max_ ( 1, seq[i].numframes - 1 ); |
295 | ipol.EndFrame = ipol.StartFrame + ipol.Frames - 1; | 295 | ipol.EndFrame = ipol.StartFrame + ipol.Frames - 1; |
296 | ipol.FramesPerSecond = seq[i].fps; | 296 | ipol.FramesPerSecond = seq[i].fps; |
297 | ipol.AnimationType = seq[i].flags & STUDIO_LOOPING ? EAMT_LOOPING : EAMT_WAYPOINT; | 297 | ipol.AnimationType = seq[i].flags & STUDIO_LOOPING ? EAMT_LOOPING : EAMT_WAYPOINT; |
298 | AnimList.push_back ( ipol ); | 298 | AnimList.push_back ( ipol ); |
299 | 299 | ||
300 | FrameCount += ipol.Frames; | 300 | FrameCount += ipol.Frames; |
301 | } | 301 | } |
302 | 302 | ||
303 | // initBoneControllers | 303 | // initBoneControllers |
304 | /* | 304 | /* |
305 | SHalflifeBoneController *bonecontroller = (SHalflifeBoneController *)((u8*) Header + Header->bonecontrollerindex); | 305 | SHalflifeBoneController *bonecontroller = (SHalflifeBoneController *)((u8*) Header + Header->bonecontrollerindex); |
306 | for ( i = 0; i < Header->numbonecontrollers; i++) | 306 | for ( i = 0; i < Header->numbonecontrollers; i++) |
307 | { | 307 | { |
308 | printf ( "BoneController%d index:%d%s range:%f - %f\n", | 308 | printf ( "BoneController%d index:%d%s range:%f - %f\n", |
309 | i, | 309 | i, |
310 | bonecontroller[i].index, bonecontroller[i].index == MOUTH_CONTROLLER ? " (Mouth)": "", | 310 | bonecontroller[i].index, bonecontroller[i].index == MOUTH_CONTROLLER ? " (Mouth)": "", |
311 | bonecontroller[i].start,bonecontroller[i].end | 311 | bonecontroller[i].start,bonecontroller[i].end |
312 | ); | 312 | ); |
313 | } | 313 | } |
314 | 314 | ||
315 | // initSkins | 315 | // initSkins |
316 | for (i = 0; i < TextureHeader->numskinfamilies; i++) | 316 | for (i = 0; i < TextureHeader->numskinfamilies; i++) |
317 | { | 317 | { |
318 | printf ( "Skin%d\n", i + 1); | 318 | printf ( "Skin%d\n", i + 1); |
319 | } | 319 | } |
320 | */ | 320 | */ |
321 | 321 | ||
322 | // initBodyparts | 322 | // initBodyparts |
323 | u32 meshBuffer = 0; | 323 | u32 meshBuffer = 0; |
324 | BodyList.clear(); | 324 | BodyList.clear(); |
325 | SHalflifeBody *body = (SHalflifeBody *) ((u8*) Header + Header->bodypartindex); | 325 | SHalflifeBody *body = (SHalflifeBody *) ((u8*) Header + Header->bodypartindex); |
326 | for (i=0; i < Header->numbodyparts; ++i) | 326 | for (i=0; i < Header->numbodyparts; ++i) |
327 | { | 327 | { |
328 | BodyPart part; | 328 | BodyPart part; |
329 | part.name = body[i].name; | 329 | part.name = body[i].name; |
330 | part.defaultModel = core::max_ ( 0, (s32) body[i].base - 1 ); | 330 | part.defaultModel = core::max_ ( 0, (s32) body[i].base - 1 ); |
331 | 331 | ||
332 | SHalflifeModel * model = (SHalflifeModel *)((u8*) Header + body[i].modelindex); | 332 | SHalflifeModel * model = (SHalflifeModel *)((u8*) Header + body[i].modelindex); |
333 | for ( u32 g = 0; g < body[i].nummodels; ++g) | 333 | for ( u32 g = 0; g < body[i].nummodels; ++g) |
334 | { | 334 | { |
335 | SubModel sub; | 335 | SubModel sub; |
336 | sub.name = model[g].name; | 336 | sub.name = model[g].name; |
337 | sub.startBuffer = meshBuffer; | 337 | sub.startBuffer = meshBuffer; |
338 | sub.endBuffer = sub.startBuffer + model[g].nummesh; | 338 | sub.endBuffer = sub.startBuffer + model[g].nummesh; |
339 | sub.state = g == part.defaultModel; | 339 | sub.state = g == part.defaultModel; |
340 | part.model.push_back ( sub ); | 340 | part.model.push_back ( sub ); |
341 | meshBuffer += model[g].nummesh; | 341 | meshBuffer += model[g].nummesh; |
342 | } | 342 | } |
343 | BodyList.push_back ( part ); | 343 | BodyList.push_back ( part ); |
344 | } | 344 | } |
345 | 345 | ||
346 | SequenceIndex = 0; | 346 | SequenceIndex = 0; |
347 | CurrentFrame = 0.f; | 347 | CurrentFrame = 0.f; |
348 | 348 | ||
349 | SetController(0, 0.f); | 349 | SetController(0, 0.f); |
350 | SetController(1, 0.f); | 350 | SetController(1, 0.f); |
351 | SetController(2, 0.f); | 351 | SetController(2, 0.f); |
352 | SetController(3, 0.f); | 352 | SetController(3, 0.f); |
353 | SetController(MOUTH_CONTROLLER, 0.f); | 353 | SetController(MOUTH_CONTROLLER, 0.f); |
354 | 354 | ||
355 | SetSkin (0); | 355 | SetSkin (0); |
356 | 356 | ||
357 | // init Meshbuffers | 357 | // init Meshbuffers |
358 | const SHalflifeTexture *tex = (SHalflifeTexture *) ((u8*) TextureHeader + TextureHeader->textureindex); | 358 | const SHalflifeTexture *tex = (SHalflifeTexture *) ((u8*) TextureHeader + TextureHeader->textureindex); |
359 | const u16 *skinref = (u16 *)((u8*)TextureHeader + TextureHeader->skinindex); | 359 | const u16 *skinref = (u16 *)((u8*)TextureHeader + TextureHeader->skinindex); |
360 | if ((SkinGroupSelection != 0) && (SkinGroupSelection < TextureHeader->numskinfamilies)) | 360 | if ((SkinGroupSelection != 0) && (SkinGroupSelection < TextureHeader->numskinfamilies)) |
361 | skinref += (SkinGroupSelection * TextureHeader->numskinref); | 361 | skinref += (SkinGroupSelection * TextureHeader->numskinref); |
362 | 362 | ||
363 | core::vector2df tex_scale; | 363 | core::vector2df tex_scale; |
364 | core::vector2di tex_trans ( 0, 0 ); | 364 | core::vector2di tex_trans ( 0, 0 ); |
365 | 365 | ||
366 | #ifdef HL_TEXTURE_ATLAS | 366 | #ifdef HL_TEXTURE_ATLAS |
367 | TextureAtlas.getScale(tex_scale); | 367 | TextureAtlas.getScale(tex_scale); |
368 | #endif | 368 | #endif |
369 | 369 | ||
370 | for (u32 bodypart=0 ; bodypart < Header->numbodyparts ; ++bodypart) | 370 | for (u32 bodypart=0 ; bodypart < Header->numbodyparts ; ++bodypart) |
371 | { | 371 | { |
372 | const SHalflifeBody *body = (SHalflifeBody *)((u8*) Header + Header->bodypartindex) + bodypart; | 372 | const SHalflifeBody *body = (SHalflifeBody *)((u8*) Header + Header->bodypartindex) + bodypart; |
373 | 373 | ||
374 | for (u32 modelnr = 0; modelnr < body->nummodels; ++modelnr) | 374 | for (u32 modelnr = 0; modelnr < body->nummodels; ++modelnr) |
375 | { | 375 | { |
376 | const SHalflifeModel *model = (SHalflifeModel *)((u8*) Header + body->modelindex) + modelnr; | 376 | const SHalflifeModel *model = (SHalflifeModel *)((u8*) Header + body->modelindex) + modelnr; |
377 | #if 0 | 377 | #if 0 |
378 | const vec3_hl *studioverts = (vec3_hl *)((u8*)Header + model->vertindex); | 378 | const vec3_hl *studioverts = (vec3_hl *)((u8*)Header + model->vertindex); |
379 | const vec3_hl *studionorms = (vec3_hl *)((u8*)Header + model->normindex); | 379 | const vec3_hl *studionorms = (vec3_hl *)((u8*)Header + model->normindex); |
380 | #endif | 380 | #endif |
381 | for (i = 0; i < model->nummesh; ++i) | 381 | for (i = 0; i < model->nummesh; ++i) |
382 | { | 382 | { |
383 | const SHalflifeMesh *mesh = (SHalflifeMesh *)((u8*)Header + model->meshindex) + i; | 383 | const SHalflifeMesh *mesh = (SHalflifeMesh *)((u8*)Header + model->meshindex) + i; |
384 | const SHalflifeTexture *currentex = &tex[skinref[mesh->skinref]]; | 384 | const SHalflifeTexture *currentex = &tex[skinref[mesh->skinref]]; |
385 | 385 | ||
386 | #ifdef HL_TEXTURE_ATLAS | 386 | #ifdef HL_TEXTURE_ATLAS |
387 | TextureAtlas.getTranslation ( currentex->name, tex_trans ); | 387 | TextureAtlas.getTranslation ( currentex->name, tex_trans ); |
388 | #else | 388 | #else |
389 | tex_scale.X = 1.f/(f32)currentex->width; | 389 | tex_scale.X = 1.f/(f32)currentex->width; |
390 | tex_scale.Y = 1.f/(f32)currentex->height; | 390 | tex_scale.Y = 1.f/(f32)currentex->height; |
391 | #endif | 391 | #endif |
392 | 392 | ||
393 | SMeshBuffer * buffer = new SMeshBuffer(); | 393 | SMeshBuffer * buffer = new SMeshBuffer(); |
394 | 394 | ||
395 | // count index vertex size indexcount = mesh->numtris * 3 | 395 | // count index vertex size indexcount = mesh->numtris * 3 |
396 | u32 indexCount = 0; | 396 | u32 indexCount = 0; |
397 | u32 vertexCount = 0; | 397 | u32 vertexCount = 0; |
398 | 398 | ||
399 | const s16 *tricmd = (s16*)((u8*)Header + mesh->triindex); | 399 | const s16 *tricmd = (s16*)((u8*)Header + mesh->triindex); |
400 | s32 c; | 400 | s32 c; |
401 | while ( (c = *(tricmd++)) ) | 401 | while ( (c = *(tricmd++)) ) |
402 | { | 402 | { |
403 | if (c < 0) | 403 | if (c < 0) |
404 | c = -c; | 404 | c = -c; |
405 | 405 | ||
406 | indexCount += ( c - 2 ) * 3; | 406 | indexCount += ( c - 2 ) * 3; |
407 | vertexCount += c; | 407 | vertexCount += c; |
408 | tricmd += ( 4 * c ); | 408 | tricmd += ( 4 * c ); |
409 | } | 409 | } |
410 | 410 | ||
411 | // indices | 411 | // indices |
412 | buffer->Indices.set_used ( indexCount ); | 412 | buffer->Indices.set_used ( indexCount ); |
413 | buffer->Vertices.set_used ( vertexCount ); | 413 | buffer->Vertices.set_used ( vertexCount ); |
414 | 414 | ||
415 | // fill in static indices and vertex | 415 | // fill in static indices and vertex |
416 | u16 *index = buffer->Indices.pointer(); | 416 | u16 *index = buffer->Indices.pointer(); |
417 | video::S3DVertex * v = buffer->Vertices.pointer(); | 417 | video::S3DVertex * v = buffer->Vertices.pointer(); |
418 | 418 | ||
419 | // blow up gl_triangle_fan/gl_triangle_strip to indexed triangle list | 419 | // blow up gl_triangle_fan/gl_triangle_strip to indexed triangle list |
420 | E_PRIMITIVE_TYPE type; | 420 | E_PRIMITIVE_TYPE type; |
421 | vertexCount = 0; | 421 | vertexCount = 0; |
422 | indexCount = 0; | 422 | indexCount = 0; |
423 | tricmd = (s16*)((u8*)Header + mesh->triindex); | 423 | tricmd = (s16*)((u8*)Header + mesh->triindex); |
424 | while ( (c = *(tricmd++)) ) | 424 | while ( (c = *(tricmd++)) ) |
425 | { | 425 | { |
426 | if (c < 0) | 426 | if (c < 0) |
427 | { | 427 | { |
428 | // triangle fan | 428 | // triangle fan |
429 | c = -c; | 429 | c = -c; |
430 | type = EPT_TRIANGLE_FAN; | 430 | type = EPT_TRIANGLE_FAN; |
431 | } | 431 | } |
432 | else | 432 | else |
433 | { | 433 | { |
434 | type = EPT_TRIANGLE_STRIP; | 434 | type = EPT_TRIANGLE_STRIP; |
435 | } | 435 | } |
436 | 436 | ||
437 | for ( s32 g = 0; g < c; ++g, v += 1, tricmd += 4 ) | 437 | for ( s32 g = 0; g < c; ++g, v += 1, tricmd += 4 ) |
438 | { | 438 | { |
439 | // fill vertex | 439 | // fill vertex |
440 | #if 0 | 440 | #if 0 |
441 | const f32 *av = studioverts[tricmd[0]]; | 441 | const f32 *av = studioverts[tricmd[0]]; |
442 | v->Pos.X = av[0]; | 442 | v->Pos.X = av[0]; |
443 | v->Pos.Z = av[1]; | 443 | v->Pos.Z = av[1]; |
444 | v->Pos.Y = av[2]; | 444 | v->Pos.Y = av[2]; |
445 | 445 | ||
446 | av = studionorms[tricmd[1]]; | 446 | av = studionorms[tricmd[1]]; |
447 | v->Normal.X = av[0]; | 447 | v->Normal.X = av[0]; |
448 | v->Normal.Z = av[1]; | 448 | v->Normal.Z = av[1]; |
449 | v->Normal.Y = av[2]; | 449 | v->Normal.Y = av[2]; |
450 | 450 | ||
451 | #endif | 451 | #endif |
452 | v->Normal.X = 0.f; | 452 | v->Normal.X = 0.f; |
453 | v->Normal.Z = 0.f; | 453 | v->Normal.Z = 0.f; |
454 | v->Normal.Y = 1.f; | 454 | v->Normal.Y = 1.f; |
455 | 455 | ||
456 | v->TCoords.X = (tex_trans.X + tricmd[2])*tex_scale.X; | 456 | v->TCoords.X = (tex_trans.X + tricmd[2])*tex_scale.X; |
457 | v->TCoords.Y = (tex_trans.Y + tricmd[3])*tex_scale.Y; | 457 | v->TCoords.Y = (tex_trans.Y + tricmd[3])*tex_scale.Y; |
458 | 458 | ||
459 | v->Color.color = 0xFFFFFFFF; | 459 | v->Color.color = 0xFFFFFFFF; |
460 | 460 | ||
461 | // fill index | 461 | // fill index |
462 | if ( g < c - 2 ) | 462 | if ( g < c - 2 ) |
463 | { | 463 | { |
464 | if ( type == EPT_TRIANGLE_FAN ) | 464 | if ( type == EPT_TRIANGLE_FAN ) |
465 | { | 465 | { |
466 | index[indexCount+0] = vertexCount; | 466 | index[indexCount+0] = vertexCount; |
467 | index[indexCount+1] = vertexCount+g+1; | 467 | index[indexCount+1] = vertexCount+g+1; |
468 | index[indexCount+2] = vertexCount+g+2; | 468 | index[indexCount+2] = vertexCount+g+2; |
469 | } | 469 | } |
470 | else | 470 | else |
471 | { | 471 | { |
472 | if ( g & 1 ) | 472 | if ( g & 1 ) |
473 | { | 473 | { |
474 | index[indexCount+0] = vertexCount+g+1; | 474 | index[indexCount+0] = vertexCount+g+1; |
475 | index[indexCount+1] = vertexCount+g+0; | 475 | index[indexCount+1] = vertexCount+g+0; |
476 | index[indexCount+2] = vertexCount+g+2; | 476 | index[indexCount+2] = vertexCount+g+2; |
477 | } | 477 | } |
478 | else | 478 | else |
479 | { | 479 | { |
480 | index[indexCount+0] = vertexCount+g+0; | 480 | index[indexCount+0] = vertexCount+g+0; |
481 | index[indexCount+1] = vertexCount+g+1; | 481 | index[indexCount+1] = vertexCount+g+1; |
482 | index[indexCount+2] = vertexCount+g+2; | 482 | index[indexCount+2] = vertexCount+g+2; |
483 | } | 483 | } |
484 | } | 484 | } |
485 | 485 | ||
486 | indexCount += 3; | 486 | indexCount += 3; |
487 | } | 487 | } |
488 | } | 488 | } |
489 | 489 | ||
490 | vertexCount += c; | 490 | vertexCount += c; |
491 | } | 491 | } |
492 | 492 | ||
493 | // material | 493 | // material |
494 | video::SMaterial &m = buffer->getMaterial(); | 494 | video::SMaterial &m = buffer->getMaterial(); |
495 | 495 | ||
496 | m.MaterialType = video::EMT_SOLID; | 496 | m.MaterialType = video::EMT_SOLID; |
497 | m.BackfaceCulling = true; | 497 | m.BackfaceCulling = true; |
498 | 498 | ||
499 | if ( currentex->flags & STUDIO_NF_CHROME ) | 499 | if ( currentex->flags & STUDIO_NF_CHROME ) |
500 | { | 500 | { |
501 | // don't know what to do with chrome here | 501 | // don't know what to do with chrome here |
502 | } | 502 | } |
503 | 503 | ||
504 | #ifdef HL_TEXTURE_ATLAS | 504 | #ifdef HL_TEXTURE_ATLAS |
505 | io::path store = TextureBaseName + "atlas"; | 505 | io::path store = TextureBaseName + "atlas"; |
506 | #else | 506 | #else |
507 | io::path fname; | 507 | io::path fname; |
508 | io::path ext; | 508 | io::path ext; |
509 | core::splitFilename ( currentex->name, 0, &fname, &ext ); | 509 | core::splitFilename ( currentex->name, 0, &fname, &ext ); |
510 | io::path store = TextureBaseName + fname; | 510 | io::path store = TextureBaseName + fname; |
511 | #endif | 511 | #endif |
512 | m.TextureLayer[0].Texture = SceneManager->getVideoDriver()->getTexture ( store ); | 512 | m.TextureLayer[0].Texture = SceneManager->getVideoDriver()->getTexture ( store ); |
513 | m.Lighting = false; | 513 | m.Lighting = false; |
514 | 514 | ||
515 | MeshIPol->addMeshBuffer(buffer); | 515 | MeshIPol->addMeshBuffer(buffer); |
516 | buffer->recalculateBoundingBox(); | 516 | buffer->recalculateBoundingBox(); |
517 | buffer->drop(); | 517 | buffer->drop(); |
518 | } // mesh | 518 | } // mesh |
519 | MeshIPol->recalculateBoundingBox(); | 519 | MeshIPol->recalculateBoundingBox(); |
520 | } // model | 520 | } // model |
521 | } // body part | 521 | } // body part |
522 | } | 522 | } |
523 | 523 | ||
524 | 524 | ||
525 | /*! | 525 | /*! |
526 | */ | 526 | */ |
527 | void CAnimatedMeshHalfLife::buildVertices() | 527 | void CAnimatedMeshHalfLife::buildVertices() |
528 | { | 528 | { |
529 | /* | 529 | /* |
530 | const u16 *skinref = (u16 *)((u8*)TextureHeader + TextureHeader->skinindex); | 530 | const u16 *skinref = (u16 *)((u8*)TextureHeader + TextureHeader->skinindex); |
531 | if (SkinGroupSelection != 0 && SkinGroupSelection < TextureHeader->numskinfamilies) | 531 | if (SkinGroupSelection != 0 && SkinGroupSelection < TextureHeader->numskinfamilies) |
532 | skinref += (SkinGroupSelection * TextureHeader->numskinref); | 532 | skinref += (SkinGroupSelection * TextureHeader->numskinref); |
533 | */ | 533 | */ |
534 | u32 i; | 534 | u32 i; |
535 | s32 c,g; | 535 | s32 c,g; |
536 | const s16 *tricmd; | 536 | const s16 *tricmd; |
537 | 537 | ||
538 | u32 meshBufferNr = 0; | 538 | u32 meshBufferNr = 0; |
539 | for ( u32 bodypart = 0 ; bodypart < Header->numbodyparts; ++bodypart) | 539 | for ( u32 bodypart = 0 ; bodypart < Header->numbodyparts; ++bodypart) |
540 | { | 540 | { |
541 | const SHalflifeBody *body = (SHalflifeBody *)((u8*) Header + Header->bodypartindex) + bodypart; | 541 | const SHalflifeBody *body = (SHalflifeBody *)((u8*) Header + Header->bodypartindex) + bodypart; |
542 | 542 | ||
543 | for ( u32 modelnr = 0; modelnr < body->nummodels; ++modelnr ) | 543 | for ( u32 modelnr = 0; modelnr < body->nummodels; ++modelnr ) |
544 | { | 544 | { |
545 | const SHalflifeModel *model = (SHalflifeModel *)((u8*) Header + body->modelindex) + modelnr; | 545 | const SHalflifeModel *model = (SHalflifeModel *)((u8*) Header + body->modelindex) + modelnr; |
546 | 546 | ||
547 | const u8 *vertbone = ((u8*)Header + model->vertinfoindex); | 547 | const u8 *vertbone = ((u8*)Header + model->vertinfoindex); |
548 | 548 | ||
549 | const vec3_hl *studioverts = (vec3_hl *)((u8*)Header + model->vertindex); | 549 | const vec3_hl *studioverts = (vec3_hl *)((u8*)Header + model->vertindex); |
550 | 550 | ||
551 | for ( i = 0; i < model->numverts; i++) | 551 | for ( i = 0; i < model->numverts; i++) |
552 | { | 552 | { |
553 | VectorTransform ( studioverts[i], BoneTransform[vertbone[i]], TransformedVerts[i] ); | 553 | VectorTransform ( studioverts[i], BoneTransform[vertbone[i]], TransformedVerts[i] ); |
554 | } | 554 | } |
555 | /* | 555 | /* |
556 | const u8 *normbone = ((u8*)Header + model->norminfoindex); | 556 | const u8 *normbone = ((u8*)Header + model->norminfoindex); |
557 | const vec3_hl *studionorms = (vec3_hl *)((u8*)Header + model->normindex); | 557 | const vec3_hl *studionorms = (vec3_hl *)((u8*)Header + model->normindex); |
558 | for ( i = 0; i < model->numnorms; i++) | 558 | for ( i = 0; i < model->numnorms; i++) |
559 | { | 559 | { |
560 | VectorTransform ( studionorms[i], BoneTransform[normbone[i]], TransformedNormals[i] ); | 560 | VectorTransform ( studionorms[i], BoneTransform[normbone[i]], TransformedNormals[i] ); |
561 | } | 561 | } |
562 | */ | 562 | */ |
563 | for (i = 0; i < model->nummesh; i++) | 563 | for (i = 0; i < model->nummesh; i++) |
564 | { | 564 | { |
565 | const SHalflifeMesh *mesh = (SHalflifeMesh *)((u8*)Header + model->meshindex) + i; | 565 | const SHalflifeMesh *mesh = (SHalflifeMesh *)((u8*)Header + model->meshindex) + i; |
566 | 566 | ||
567 | IMeshBuffer * buffer = MeshIPol->getMeshBuffer ( meshBufferNr++ ); | 567 | IMeshBuffer * buffer = MeshIPol->getMeshBuffer ( meshBufferNr++ ); |
568 | video::S3DVertex* v = (video::S3DVertex* ) buffer->getVertices(); | 568 | video::S3DVertex* v = (video::S3DVertex* ) buffer->getVertices(); |
569 | 569 | ||
570 | tricmd = (s16*)((u8*)Header + mesh->triindex); | 570 | tricmd = (s16*)((u8*)Header + mesh->triindex); |
571 | while ( (c = *(tricmd++)) ) | 571 | while ( (c = *(tricmd++)) ) |
572 | { | 572 | { |
573 | if (c < 0) | 573 | if (c < 0) |
574 | c = -c; | 574 | c = -c; |
575 | 575 | ||
576 | for ( g = 0; g < c; ++g, v += 1, tricmd += 4 ) | 576 | for ( g = 0; g < c; ++g, v += 1, tricmd += 4 ) |
577 | { | 577 | { |
578 | // fill vertex | 578 | // fill vertex |
579 | const core::vector3df& av = TransformedVerts[tricmd[0]]; | 579 | const core::vector3df& av = TransformedVerts[tricmd[0]]; |
580 | v->Pos = av; | 580 | v->Pos = av; |
581 | /* | 581 | /* |
582 | const core::vector3df& an = TransformedNormals[tricmd[1]]; | 582 | const core::vector3df& an = TransformedNormals[tricmd[1]]; |
583 | v->Normal = an; | 583 | v->Normal = an; |
584 | //v->Normal.normalize(); | 584 | //v->Normal.normalize(); |
585 | */ | 585 | */ |
586 | } | 586 | } |
587 | } // tricmd | 587 | } // tricmd |
588 | } // nummesh | 588 | } // nummesh |
589 | } // model | 589 | } // model |
590 | } // bodypart | 590 | } // bodypart |
591 | } | 591 | } |
592 | 592 | ||
593 | 593 | ||
594 | /*! | 594 | /*! |
595 | render Bones | 595 | render Bones |
596 | */ | 596 | */ |
597 | void CAnimatedMeshHalfLife::renderModel(u32 param, IVideoDriver * driver, const core::matrix4 &absoluteTransformation) | 597 | void CAnimatedMeshHalfLife::renderModel(u32 param, IVideoDriver * driver, const core::matrix4 &absoluteTransformation) |
598 | { | 598 | { |
599 | SHalflifeBone *bone = (SHalflifeBone *) ((u8 *) Header + Header->boneindex); | 599 | SHalflifeBone *bone = (SHalflifeBone *) ((u8 *) Header + Header->boneindex); |
600 | 600 | ||
601 | video::SColor blue(0xFF000080); | 601 | video::SColor blue(0xFF000080); |
602 | video::SColor red(0xFF800000); | 602 | video::SColor red(0xFF800000); |
603 | video::SColor yellow(0xFF808000); | 603 | video::SColor yellow(0xFF808000); |
604 | video::SColor cyan(0xFF008080); | 604 | video::SColor cyan(0xFF008080); |
605 | 605 | ||
606 | core::aabbox3df box; | 606 | core::aabbox3df box; |
607 | 607 | ||
608 | u32 i; | 608 | u32 i; |
609 | for ( i = 0; i < Header->numbones; i++) | 609 | for ( i = 0; i < Header->numbones; i++) |
610 | { | 610 | { |
611 | if (bone[i].parent >= 0) | 611 | if (bone[i].parent >= 0) |
612 | { | 612 | { |
613 | getBoneVector ( box.MinEdge, bone[i].parent ); | 613 | getBoneVector ( box.MinEdge, bone[i].parent ); |
614 | getBoneVector ( box.MaxEdge, i ); | 614 | getBoneVector ( box.MaxEdge, i ); |
615 | driver->draw3DLine ( box.MinEdge, box.MaxEdge, blue ); | 615 | driver->draw3DLine ( box.MinEdge, box.MaxEdge, blue ); |
616 | 616 | ||
617 | // draw parent bone node | 617 | // draw parent bone node |
618 | if (bone[bone[i].parent].parent >=0 ) | 618 | if (bone[bone[i].parent].parent >=0 ) |
619 | { | 619 | { |
620 | getBoneBox ( box, bone[i].parent ); | 620 | getBoneBox ( box, bone[i].parent ); |
621 | driver->draw3DBox ( box, blue ); | 621 | driver->draw3DBox ( box, blue ); |
622 | } | 622 | } |
623 | getBoneBox ( box, i ); | 623 | getBoneBox ( box, i ); |
624 | driver->draw3DBox ( box, blue ); | 624 | driver->draw3DBox ( box, blue ); |
625 | } | 625 | } |
626 | else | 626 | else |
627 | { | 627 | { |
628 | // draw parent bone node | 628 | // draw parent bone node |
629 | getBoneBox ( box, i, 1.f ); | 629 | getBoneBox ( box, i, 1.f ); |
630 | driver->draw3DBox ( box , red ); | 630 | driver->draw3DBox ( box , red ); |
631 | } | 631 | } |
632 | } | 632 | } |
633 | 633 | ||
634 | // attachements | 634 | // attachements |
635 | SHalflifeAttachment *attach = (SHalflifeAttachment *) ((u8*) Header + Header->attachmentindex); | 635 | SHalflifeAttachment *attach = (SHalflifeAttachment *) ((u8*) Header + Header->attachmentindex); |
636 | core::vector3df v[8]; | 636 | core::vector3df v[8]; |
637 | for ( i = 0; i < Header->numattachments; i++) | 637 | for ( i = 0; i < Header->numattachments; i++) |
638 | { | 638 | { |
639 | getTransformedBoneVector ( v[0],attach[i].bone,attach[i].org ); | 639 | getTransformedBoneVector ( v[0],attach[i].bone,attach[i].org ); |
640 | getTransformedBoneVector ( v[1],attach[i].bone,attach[i].vectors[0] ); | 640 | getTransformedBoneVector ( v[1],attach[i].bone,attach[i].vectors[0] ); |
641 | getTransformedBoneVector ( v[2],attach[i].bone,attach[i].vectors[1] ); | 641 | getTransformedBoneVector ( v[2],attach[i].bone,attach[i].vectors[1] ); |
642 | getTransformedBoneVector ( v[3],attach[i].bone,attach[i].vectors[2] ); | 642 | getTransformedBoneVector ( v[3],attach[i].bone,attach[i].vectors[2] ); |
643 | driver->draw3DLine ( v[0], v[1], cyan ); | 643 | driver->draw3DLine ( v[0], v[1], cyan ); |
644 | driver->draw3DLine ( v[0], v[2], cyan ); | 644 | driver->draw3DLine ( v[0], v[2], cyan ); |
645 | driver->draw3DLine ( v[0], v[3], cyan ); | 645 | driver->draw3DLine ( v[0], v[3], cyan ); |
646 | } | 646 | } |
647 | 647 | ||
648 | // hit boxes | 648 | // hit boxes |
649 | SHalflifeBBox *hitbox = (SHalflifeBBox *) ((u8*) Header + Header->hitboxindex); | 649 | SHalflifeBBox *hitbox = (SHalflifeBBox *) ((u8*) Header + Header->hitboxindex); |
650 | f32 *bbmin,*bbmax; | 650 | f32 *bbmin,*bbmax; |
651 | vec3_hl v2[8]; | 651 | vec3_hl v2[8]; |
652 | for (i = 0; i < Header->numhitboxes; i++) | 652 | for (i = 0; i < Header->numhitboxes; i++) |
653 | { | 653 | { |
654 | bbmin = hitbox[i].bbmin; | 654 | bbmin = hitbox[i].bbmin; |
655 | bbmax = hitbox[i].bbmax; | 655 | bbmax = hitbox[i].bbmax; |
656 | 656 | ||
657 | v2[0][0] = bbmin[0]; | 657 | v2[0][0] = bbmin[0]; |
658 | v2[0][1] = bbmax[1]; | 658 | v2[0][1] = bbmax[1]; |
659 | v2[0][2] = bbmin[2]; | 659 | v2[0][2] = bbmin[2]; |
660 | 660 | ||
661 | v2[1][0] = bbmin[0]; | 661 | v2[1][0] = bbmin[0]; |
662 | v2[1][1] = bbmin[1]; | 662 | v2[1][1] = bbmin[1]; |
663 | v2[1][2] = bbmin[2]; | 663 | v2[1][2] = bbmin[2]; |
664 | 664 | ||
665 | v2[2][0] = bbmax[0]; | 665 | v2[2][0] = bbmax[0]; |
666 | v2[2][1] = bbmax[1]; | 666 | v2[2][1] = bbmax[1]; |
667 | v2[2][2] = bbmin[2]; | 667 | v2[2][2] = bbmin[2]; |
668 | 668 | ||
669 | v2[3][0] = bbmax[0]; | 669 | v2[3][0] = bbmax[0]; |
670 | v2[3][1] = bbmin[1]; | 670 | v2[3][1] = bbmin[1]; |
671 | v2[3][2] = bbmin[2]; | 671 | v2[3][2] = bbmin[2]; |
672 | 672 | ||
673 | v2[4][0] = bbmax[0]; | 673 | v2[4][0] = bbmax[0]; |
674 | v2[4][1] = bbmax[1]; | 674 | v2[4][1] = bbmax[1]; |
675 | v2[4][2] = bbmax[2]; | 675 | v2[4][2] = bbmax[2]; |
676 | 676 | ||
677 | v2[5][0] = bbmax[0]; | 677 | v2[5][0] = bbmax[0]; |
678 | v2[5][1] = bbmin[1]; | 678 | v2[5][1] = bbmin[1]; |
679 | v2[5][2] = bbmax[2]; | 679 | v2[5][2] = bbmax[2]; |
680 | 680 | ||
681 | v2[6][0] = bbmin[0]; | 681 | v2[6][0] = bbmin[0]; |
682 | v2[6][1] = bbmax[1]; | 682 | v2[6][1] = bbmax[1]; |
683 | v2[6][2] = bbmax[2]; | 683 | v2[6][2] = bbmax[2]; |
684 | 684 | ||
685 | v2[7][0] = bbmin[0]; | 685 | v2[7][0] = bbmin[0]; |
686 | v2[7][1] = bbmin[1]; | 686 | v2[7][1] = bbmin[1]; |
687 | v2[7][2] = bbmax[2]; | 687 | v2[7][2] = bbmax[2]; |
688 | 688 | ||
689 | for ( u32 g = 0; g < 8; ++g ) | 689 | for ( u32 g = 0; g < 8; ++g ) |
690 | getTransformedBoneVector ( v[g],hitbox[i].bone,v2[g] ); | 690 | getTransformedBoneVector ( v[g],hitbox[i].bone,v2[g] ); |
691 | 691 | ||
692 | driver->draw3DLine(v[0], v[1], yellow); | 692 | driver->draw3DLine(v[0], v[1], yellow); |
693 | driver->draw3DLine(v[1], v[3], yellow); | 693 | driver->draw3DLine(v[1], v[3], yellow); |
694 | driver->draw3DLine(v[3], v[2], yellow); | 694 | driver->draw3DLine(v[3], v[2], yellow); |
695 | driver->draw3DLine(v[2], v[0], yellow); | 695 | driver->draw3DLine(v[2], v[0], yellow); |
696 | 696 | ||
697 | driver->draw3DLine(v[4], v[5], yellow); | 697 | driver->draw3DLine(v[4], v[5], yellow); |
698 | driver->draw3DLine(v[5], v[7], yellow); | 698 | driver->draw3DLine(v[5], v[7], yellow); |
699 | driver->draw3DLine(v[7], v[6], yellow); | 699 | driver->draw3DLine(v[7], v[6], yellow); |
700 | driver->draw3DLine(v[6], v[4], yellow); | 700 | driver->draw3DLine(v[6], v[4], yellow); |
701 | 701 | ||
702 | driver->draw3DLine(v[0], v[6], yellow); | 702 | driver->draw3DLine(v[0], v[6], yellow); |
703 | driver->draw3DLine(v[1], v[7], yellow); | 703 | driver->draw3DLine(v[1], v[7], yellow); |
704 | driver->draw3DLine(v[3], v[5], yellow); | 704 | driver->draw3DLine(v[3], v[5], yellow); |
705 | driver->draw3DLine(v[2], v[4], yellow); | 705 | driver->draw3DLine(v[2], v[4], yellow); |
706 | } | 706 | } |
707 | } | 707 | } |
708 | 708 | ||
709 | 709 | ||
710 | //! Returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. | 710 | //! Returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. |
711 | IMesh* CAnimatedMeshHalfLife::getMesh(s32 frameInt, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) | 711 | IMesh* CAnimatedMeshHalfLife::getMesh(s32 frameInt, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) |
712 | { | 712 | { |
713 | f32 frame = frameInt + (detailLevel * 0.001f); | 713 | f32 frame = frameInt + (detailLevel * 0.001f); |
714 | u32 frameA = core::floor32 ( frame ); | 714 | u32 frameA = core::floor32 ( frame ); |
715 | // f32 blend = core::fract ( frame ); | 715 | // f32 blend = core::fract ( frame ); |
716 | 716 | ||
717 | SHalflifeSequence *seq = (SHalflifeSequence*) ((u8*) Header + Header->seqindex); | 717 | SHalflifeSequence *seq = (SHalflifeSequence*) ((u8*) Header + Header->seqindex); |
718 | 718 | ||
719 | // find SequenceIndex from summed list | 719 | // find SequenceIndex from summed list |
720 | u32 frameCount = 0; | 720 | u32 frameCount = 0; |
721 | for (u32 i = 0; i < Header->numseq; ++i) | 721 | for (u32 i = 0; i < Header->numseq; ++i) |
722 | { | 722 | { |
723 | u32 val = core::max_ ( 1, seq[i].numframes - 1 ); | 723 | u32 val = core::max_ ( 1, seq[i].numframes - 1 ); |
724 | if ( frameCount + val > frameA ) | 724 | if ( frameCount + val > frameA ) |
725 | { | 725 | { |
726 | SequenceIndex = i; | 726 | SequenceIndex = i; |
727 | CurrentFrame = frame - frameCount; | 727 | CurrentFrame = frame - frameCount; |
728 | break; | 728 | break; |
729 | } | 729 | } |
730 | frameCount += val; | 730 | frameCount += val; |
731 | } | 731 | } |
732 | 732 | ||
733 | seq += SequenceIndex; | 733 | seq += SequenceIndex; |
734 | 734 | ||
735 | //SetBodyPart ( 1, 1 ); | 735 | //SetBodyPart ( 1, 1 ); |
736 | setUpBones (); | 736 | setUpBones (); |
737 | buildVertices(); | 737 | buildVertices(); |
738 | 738 | ||
739 | MeshIPol->BoundingBox.MinEdge.X = seq->bbmin[0]; | 739 | MeshIPol->BoundingBox.MinEdge.X = seq->bbmin[0]; |
740 | MeshIPol->BoundingBox.MinEdge.Z = seq->bbmin[1]; | 740 | MeshIPol->BoundingBox.MinEdge.Z = seq->bbmin[1]; |
741 | MeshIPol->BoundingBox.MinEdge.Y = seq->bbmin[2]; | 741 | MeshIPol->BoundingBox.MinEdge.Y = seq->bbmin[2]; |
742 | 742 | ||
743 | MeshIPol->BoundingBox.MaxEdge.X = seq->bbmax[0]; | 743 | MeshIPol->BoundingBox.MaxEdge.X = seq->bbmax[0]; |
744 | MeshIPol->BoundingBox.MaxEdge.Z = seq->bbmax[1]; | 744 | MeshIPol->BoundingBox.MaxEdge.Z = seq->bbmax[1]; |
745 | MeshIPol->BoundingBox.MaxEdge.Y = seq->bbmax[2]; | 745 | MeshIPol->BoundingBox.MaxEdge.Y = seq->bbmax[2]; |
746 | 746 | ||
747 | return MeshIPol; | 747 | return MeshIPol; |
748 | } | 748 | } |
749 | 749 | ||
750 | 750 | ||
751 | /*! | 751 | /*! |
752 | */ | 752 | */ |
753 | void CAnimatedMeshHalfLife::initData () | 753 | void CAnimatedMeshHalfLife::initData () |
754 | { | 754 | { |
755 | u32 i; | 755 | u32 i; |
756 | 756 | ||
757 | Header = 0; | 757 | Header = 0; |
758 | TextureHeader = 0; | 758 | TextureHeader = 0; |
759 | OwnTexModel = false; | 759 | OwnTexModel = false; |
760 | 760 | ||
761 | for ( i = 0; i < 32; ++i ) | 761 | for ( i = 0; i < 32; ++i ) |
762 | AnimationHeader[i] = 0; | 762 | AnimationHeader[i] = 0; |
763 | 763 | ||
764 | SequenceIndex = 0; | 764 | SequenceIndex = 0; |
765 | CurrentFrame = 0.f; | 765 | CurrentFrame = 0.f; |
766 | 766 | ||
767 | for ( i = 0; i < 5; ++i ) | 767 | for ( i = 0; i < 5; ++i ) |
768 | BoneController[i] = 0; | 768 | BoneController[i] = 0; |
769 | 769 | ||
770 | for ( i = 0; i < 2; ++i ) | 770 | for ( i = 0; i < 2; ++i ) |
771 | Blending[i] = 0; | 771 | Blending[i] = 0; |
772 | 772 | ||
773 | SkinGroupSelection = 0; | 773 | SkinGroupSelection = 0; |
774 | 774 | ||
775 | AnimList.clear(); | 775 | AnimList.clear(); |
776 | FrameCount = 0; | 776 | FrameCount = 0; |
777 | 777 | ||
778 | if (!MeshIPol) | 778 | if (!MeshIPol) |
779 | MeshIPol = new SMesh(); | 779 | MeshIPol = new SMesh(); |
780 | MeshIPol->clear(); | 780 | MeshIPol->clear(); |
781 | 781 | ||
782 | #ifdef HL_TEXTURE_ATLAS | 782 | #ifdef HL_TEXTURE_ATLAS |
783 | TextureAtlas.release(); | 783 | TextureAtlas.release(); |
784 | #endif | 784 | #endif |
785 | } | 785 | } |
786 | 786 | ||
787 | 787 | ||
788 | /*! | 788 | /*! |
789 | */ | 789 | */ |
790 | void STextureAtlas::release() | 790 | void STextureAtlas::release() |
791 | { | 791 | { |
792 | for (u32 i = 0; i < atlas.size(); i++) | 792 | for (u32 i = 0; i < atlas.size(); i++) |
793 | { | 793 | { |
794 | if ( atlas[i].image ) | 794 | if ( atlas[i].image ) |
795 | { | 795 | { |
796 | atlas[i].image->drop(); | 796 | atlas[i].image->drop(); |
797 | atlas[i].image = 0; | 797 | atlas[i].image = 0; |
798 | } | 798 | } |
799 | } | 799 | } |
800 | Master = 0; | 800 | Master = 0; |
801 | } | 801 | } |
802 | 802 | ||
803 | 803 | ||
804 | /*! | 804 | /*! |
805 | */ | 805 | */ |
806 | void STextureAtlas::addSource ( const c8 * name, video::IImage * image ) | 806 | void STextureAtlas::addSource ( const c8 * name, video::IImage * image ) |
807 | { | 807 | { |
808 | TextureAtlasEntry entry; | 808 | TextureAtlasEntry entry; |
809 | entry.name = name; | 809 | entry.name = name; |
810 | entry.image = image; | 810 | entry.image = image; |
811 | entry.width = image->getDimension().Width; | 811 | entry.width = image->getDimension().Width; |
812 | entry.height = image->getDimension().Height; | 812 | entry.height = image->getDimension().Height; |
813 | entry.pos.X = 0; | 813 | entry.pos.X = 0; |
814 | entry.pos.Y = 0; | 814 | entry.pos.Y = 0; |
815 | atlas.push_back ( entry ); | 815 | atlas.push_back ( entry ); |
816 | } | 816 | } |
817 | 817 | ||
818 | 818 | ||
819 | /*! | 819 | /*! |
820 | */ | 820 | */ |
821 | void STextureAtlas::getScale(core::vector2df& scale) | 821 | void STextureAtlas::getScale(core::vector2df& scale) |
822 | { | 822 | { |
823 | for (s32 i = static_cast<s32>(atlas.size()) - 1; i >= 0; --i) | 823 | for (s32 i = static_cast<s32>(atlas.size()) - 1; i >= 0; --i) |
824 | { | 824 | { |
825 | if ( atlas[i].name == "_merged_" ) | 825 | if ( atlas[i].name == "_merged_" ) |
826 | { | 826 | { |
827 | scale.X = 1.f / atlas[i].width; | 827 | scale.X = 1.f / atlas[i].width; |
828 | scale.Y = 1.f / atlas[i].height; | 828 | scale.Y = 1.f / atlas[i].height; |
829 | return; | 829 | return; |
830 | } | 830 | } |
831 | } | 831 | } |
832 | scale.X = 1.f; | 832 | scale.X = 1.f; |
833 | scale.Y = 1.f; | 833 | scale.Y = 1.f; |
834 | } | 834 | } |
835 | 835 | ||
836 | 836 | ||
837 | /*! | 837 | /*! |
838 | */ | 838 | */ |
839 | void STextureAtlas::getTranslation(const c8* name, core::vector2di& pos) | 839 | void STextureAtlas::getTranslation(const c8* name, core::vector2di& pos) |
840 | { | 840 | { |
841 | for ( u32 i = 0; i < atlas.size(); ++i) | 841 | for ( u32 i = 0; i < atlas.size(); ++i) |
842 | { | 842 | { |
843 | if ( atlas[i].name == name ) | 843 | if ( atlas[i].name == name ) |
844 | { | 844 | { |
845 | pos = atlas[i].pos; | 845 | pos = atlas[i].pos; |
846 | return; | 846 | return; |
847 | } | 847 | } |
848 | } | 848 | } |
849 | } | 849 | } |
850 | 850 | ||
851 | 851 | ||
852 | /*! | 852 | /*! |
853 | */ | 853 | */ |
854 | void STextureAtlas::create(u32 border, E_TEXTURE_CLAMP texmode) | 854 | void STextureAtlas::create(u32 border, E_TEXTURE_CLAMP texmode) |
855 | { | 855 | { |
856 | u32 i = 0; | 856 | u32 i = 0; |
857 | u32 w = 0; | 857 | u32 w = 0; |
858 | u32 w2; | 858 | u32 w2; |
859 | u32 h2; | 859 | u32 h2; |
860 | u32 h; | 860 | u32 h; |
861 | u32 wsum; | 861 | u32 wsum; |
862 | u32 hsum = 0; | 862 | u32 hsum = 0; |
863 | ECOLOR_FORMAT format = ECF_R8G8B8; | 863 | ECOLOR_FORMAT format = ECF_R8G8B8; |
864 | 864 | ||
865 | const s32 frame = core::s32_max ( 0, (border - 1 ) / 2 ); | 865 | const s32 frame = core::s32_max ( 0, (border - 1 ) / 2 ); |
866 | 866 | ||
867 | // sort for biggest coming first | 867 | // sort for biggest coming first |
868 | atlas.sort(); | 868 | atlas.sort(); |
869 | 869 | ||
870 | // split size | 870 | // split size |
871 | wsum = frame; | 871 | wsum = frame; |
872 | for (i = 0; i < atlas.size(); i++) | 872 | for (i = 0; i < atlas.size(); i++) |
873 | { | 873 | { |
874 | // make space | 874 | // make space |
875 | w2 = atlas[i].width + border; | 875 | w2 = atlas[i].width + border; |
876 | 876 | ||
877 | // align | 877 | // align |
878 | w2 = (w2 + 1) & ~1; | 878 | w2 = (w2 + 1) & ~1; |
879 | wsum += w2; | 879 | wsum += w2; |
880 | } | 880 | } |
881 | u32 splitsize = 256; | 881 | u32 splitsize = 256; |
882 | if ( wsum > 512 ) | 882 | if ( wsum > 512 ) |
883 | splitsize = 512; | 883 | splitsize = 512; |
884 | 884 | ||
885 | wsum = frame; | 885 | wsum = frame; |
886 | hsum = frame; | 886 | hsum = frame; |
887 | w = frame; | 887 | w = frame; |
888 | h = 0; | 888 | h = 0; |
889 | for (i = 0; i < atlas.size(); i++) | 889 | for (i = 0; i < atlas.size(); i++) |
890 | { | 890 | { |
891 | if ( atlas[i].image->getColorFormat() == ECF_A8R8G8B8 ) | 891 | if ( atlas[i].image->getColorFormat() == ECF_A8R8G8B8 ) |
892 | { | 892 | { |
893 | format = ECF_A8R8G8B8; | 893 | format = ECF_A8R8G8B8; |
894 | } | 894 | } |
895 | 895 | ||
896 | // make space | 896 | // make space |
897 | w2 = atlas[i].width + border; | 897 | w2 = atlas[i].width + border; |
898 | h2 = atlas[i].height + border; | 898 | h2 = atlas[i].height + border; |
899 | 899 | ||
900 | // align | 900 | // align |
901 | w2 = (w2 + 1) & ~1; | 901 | w2 = (w2 + 1) & ~1; |
902 | h2 = (h2 + 1) & ~1; | 902 | h2 = (h2 + 1) & ~1; |
903 | 903 | ||
904 | h = core::s32_max ( h, h2 ); | 904 | h = core::s32_max ( h, h2 ); |
905 | 905 | ||
906 | if ( w + w2 >= splitsize ) | 906 | if ( w + w2 >= splitsize ) |
907 | { | 907 | { |
908 | hsum += h; | 908 | hsum += h; |
909 | wsum = core::s32_max ( wsum, w ); | 909 | wsum = core::s32_max ( wsum, w ); |
910 | h = h2; | 910 | h = h2; |
911 | w = frame; | 911 | w = frame; |
912 | } | 912 | } |
913 | 913 | ||
914 | atlas[i].pos.X = w; | 914 | atlas[i].pos.X = w; |
915 | atlas[i].pos.Y = hsum; | 915 | atlas[i].pos.Y = hsum; |
916 | 916 | ||
917 | w += w2; | 917 | w += w2; |
918 | 918 | ||
919 | } | 919 | } |
920 | hsum += h; | 920 | hsum += h; |
921 | wsum = core::s32_max ( wsum, w ); | 921 | wsum = core::s32_max ( wsum, w ); |
922 | 922 | ||
923 | // build image | 923 | // build image |
924 | core::dimension2d<u32> dim = core::dimension2d<u32>( wsum, hsum ).getOptimalSize(); | 924 | core::dimension2d<u32> dim = core::dimension2d<u32>( wsum, hsum ).getOptimalSize(); |
925 | IImage* master = new CImage(format, dim); | 925 | IImage* master = new CImage(format, dim); |
926 | master->fill(0); | 926 | master->fill(0); |
927 | 927 | ||
928 | video::SColor col[2]; | 928 | video::SColor col[2]; |
929 | 929 | ||
930 | static const u8 wrap[][4] = | 930 | static const u8 wrap[][4] = |
931 | { | 931 | { |
932 | {1, 0}, // ETC_REPEAT | 932 | {1, 0}, // ETC_REPEAT |
933 | {0, 1}, // ETC_CLAMP | 933 | {0, 1}, // ETC_CLAMP |
934 | {0, 1}, // ETC_CLAMP_TO_EDGE | 934 | {0, 1}, // ETC_CLAMP_TO_EDGE |
935 | {0, 1} // ETC_MIRROR | 935 | {0, 1} // ETC_MIRROR |
936 | }; | 936 | }; |
937 | 937 | ||
938 | s32 a,b; | 938 | s32 a,b; |
939 | for (i = 0; i < atlas.size(); i++) | 939 | for (i = 0; i < atlas.size(); i++) |
940 | { | 940 | { |
941 | atlas[i].image->copyTo ( master, atlas[i].pos ); | 941 | atlas[i].image->copyTo ( master, atlas[i].pos ); |
942 | 942 | ||
943 | // clamp/wrap ( copy edges, filtering needs it ) | 943 | // clamp/wrap ( copy edges, filtering needs it ) |
944 | 944 | ||
945 | for ( b = 0; b < frame; ++b ) | 945 | for ( b = 0; b < frame; ++b ) |
946 | { | 946 | { |
947 | for ( a = 0 - b; a <= (s32) atlas[i].width + b; ++a ) | 947 | for ( a = 0 - b; a <= (s32) atlas[i].width + b; ++a ) |
948 | { | 948 | { |
949 | col[0] = atlas[i].image->getPixel ( core::s32_clamp ( a, 0, atlas[i].width - 1 ), 0 ); | 949 | col[0] = atlas[i].image->getPixel ( core::s32_clamp ( a, 0, atlas[i].width - 1 ), 0 ); |
950 | col[1] = atlas[i].image->getPixel ( core::s32_clamp ( a, 0, atlas[i].width - 1 ), atlas[i].height - 1 ); | 950 | col[1] = atlas[i].image->getPixel ( core::s32_clamp ( a, 0, atlas[i].width - 1 ), atlas[i].height - 1 ); |
951 | 951 | ||
952 | master->setPixel ( atlas[i].pos.X + a, atlas[i].pos.Y + ( b + 1 ) * -1, col[wrap[texmode][0]] ); | 952 | master->setPixel ( atlas[i].pos.X + a, atlas[i].pos.Y + ( b + 1 ) * -1, col[wrap[texmode][0]] ); |
953 | master->setPixel ( atlas[i].pos.X + a, atlas[i].pos.Y + atlas[i].height - 1 + ( b + 1 ) * 1, col[wrap[texmode][1]] ); | 953 | master->setPixel ( atlas[i].pos.X + a, atlas[i].pos.Y + atlas[i].height - 1 + ( b + 1 ) * 1, col[wrap[texmode][1]] ); |
954 | } | 954 | } |
955 | 955 | ||
956 | for ( a = -1 - b; a <= (s32) atlas[i].height + b; ++a ) | 956 | for ( a = -1 - b; a <= (s32) atlas[i].height + b; ++a ) |
957 | { | 957 | { |
958 | col[0] = atlas[i].image->getPixel ( 0, core::s32_clamp ( a, 0, atlas[i].height - 1 ) ); | 958 | col[0] = atlas[i].image->getPixel ( 0, core::s32_clamp ( a, 0, atlas[i].height - 1 ) ); |
959 | col[1] = atlas[i].image->getPixel ( atlas[i].width - 1, core::s32_clamp ( a, 0, atlas[i].height - 1 ) ); | 959 | col[1] = atlas[i].image->getPixel ( atlas[i].width - 1, core::s32_clamp ( a, 0, atlas[i].height - 1 ) ); |
960 | 960 | ||
961 | master->setPixel ( atlas[i].pos.X + ( b + 1 ) * -1, atlas[i].pos.Y + a, col[wrap[texmode][0]] ); | 961 | master->setPixel ( atlas[i].pos.X + ( b + 1 ) * -1, atlas[i].pos.Y + a, col[wrap[texmode][0]] ); |
962 | master->setPixel ( atlas[i].pos.X + atlas[i].width + b, atlas[i].pos.Y + a, col[wrap[texmode][1]] ); | 962 | master->setPixel ( atlas[i].pos.X + atlas[i].width + b, atlas[i].pos.Y + a, col[wrap[texmode][1]] ); |
963 | } | 963 | } |
964 | } | 964 | } |
965 | } | 965 | } |
966 | 966 | ||
967 | addSource ( "_merged_", master ); | 967 | addSource ( "_merged_", master ); |
968 | Master = master; | 968 | Master = master; |
969 | } | 969 | } |
970 | 970 | ||
971 | 971 | ||
972 | /*! | 972 | /*! |
973 | */ | 973 | */ |
974 | SHalflifeHeader* CAnimatedMeshHalfLife::loadModel(io::IReadFile* file, const io::path& filename) | 974 | SHalflifeHeader* CAnimatedMeshHalfLife::loadModel(io::IReadFile* file, const io::path& filename) |
975 | { | 975 | { |
976 | bool closefile = false; | 976 | bool closefile = false; |
977 | 977 | ||
978 | // if secondary files are needed, open here and mark for closing | 978 | // if secondary files are needed, open here and mark for closing |
979 | if ( 0 == file ) | 979 | if ( 0 == file ) |
980 | { | 980 | { |
981 | file = SceneManager->getFileSystem()->createAndOpenFile(filename); | 981 | file = SceneManager->getFileSystem()->createAndOpenFile(filename); |
982 | closefile = true; | 982 | closefile = true; |
983 | } | 983 | } |
984 | 984 | ||
985 | if ( 0 == file ) | 985 | if ( 0 == file ) |
986 | return 0; | 986 | return 0; |
987 | 987 | ||
988 | // read into memory | 988 | // read into memory |
989 | u8* pin = new u8[file->getSize()]; | 989 | u8* pin = new u8[file->getSize()]; |
990 | file->read(pin, file->getSize()); | 990 | file->read(pin, file->getSize()); |
991 | 991 | ||
992 | SHalflifeHeader* header = (SHalflifeHeader*) pin; | 992 | SHalflifeHeader* header = (SHalflifeHeader*) pin; |
993 | 993 | ||
994 | const bool idst = (0 == strncmp(header->id, "IDST", 4)); | 994 | const bool idst = (0 == strncmp(header->id, "IDST", 4)); |
995 | const bool idsq = (0 == strncmp(header->id, "IDSQ", 4)); | 995 | const bool idsq = (0 == strncmp(header->id, "IDSQ", 4)); |
996 | 996 | ||
997 | if ( (!idst && !idsq) || (idsq && !Header) ) | 997 | if ( (!idst && !idsq) || (idsq && !Header) ) |
998 | { | 998 | { |
999 | os::Printer::log("MDL Halflife Loader: Wrong file header", file->getFileName(), ELL_WARNING); | 999 | os::Printer::log("MDL Halflife Loader: Wrong file header", file->getFileName(), ELL_WARNING); |
1000 | if ( closefile ) | 1000 | if ( closefile ) |
1001 | { | 1001 | { |
1002 | file->drop(); | 1002 | file->drop(); |
1003 | file = 0; | 1003 | file = 0; |
1004 | } | 1004 | } |
1005 | delete [] pin; | 1005 | delete [] pin; |
1006 | return 0; | 1006 | return 0; |
1007 | } | 1007 | } |
1008 | 1008 | ||
1009 | // don't know the real header.. idsg might be different | 1009 | // don't know the real header.. idsg might be different |
1010 | if (header->textureindex && idst ) | 1010 | if (header->textureindex && idst ) |
1011 | { | 1011 | { |
1012 | io::path path; | 1012 | io::path path; |
1013 | io::path fname; | 1013 | io::path fname; |
1014 | io::path ext; | 1014 | io::path ext; |
1015 | 1015 | ||
1016 | core::splitFilename(file->getFileName(), &path, &fname, &ext); | 1016 | core::splitFilename(file->getFileName(), &path, &fname, &ext); |
1017 | TextureBaseName = path + fname + "_"; | 1017 | TextureBaseName = path + fname + "_"; |
1018 | 1018 | ||
1019 | SHalflifeTexture *tex = (SHalflifeTexture *)(pin + header->textureindex); | 1019 | SHalflifeTexture *tex = (SHalflifeTexture *)(pin + header->textureindex); |
1020 | u32 *palette = new u32[256]; | 1020 | u32 *palette = new u32[256]; |
1021 | for (u32 i = 0; i < header->numtextures; ++i) | 1021 | for (u32 i = 0; i < header->numtextures; ++i) |
1022 | { | 1022 | { |
1023 | const u8 *src = pin + tex[i].index; | 1023 | const u8 *src = pin + tex[i].index; |
1024 | 1024 | ||
1025 | // convert rgb to argb palette | 1025 | // convert rgb to argb palette |
1026 | { | 1026 | { |
1027 | const u8 *pal = src + tex[i].width * tex[i].height; | 1027 | const u8 *pal = src + tex[i].width * tex[i].height; |
1028 | for( u32 g=0; g<256; ++g ) | 1028 | for( u32 g=0; g<256; ++g ) |
1029 | { | 1029 | { |
1030 | palette[g] = 0xFF000000 | pal[0] << 16 | pal[1] << 8 | pal[2]; | 1030 | palette[g] = 0xFF000000 | pal[0] << 16 | pal[1] << 8 | pal[2]; |
1031 | pal += 3; | 1031 | pal += 3; |
1032 | } | 1032 | } |
1033 | } | 1033 | } |
1034 | 1034 | ||
1035 | IImage* image = SceneManager->getVideoDriver()->createImage(ECF_R8G8B8, core::dimension2d<u32>(tex[i].width, tex[i].height)); | 1035 | IImage* image = SceneManager->getVideoDriver()->createImage(ECF_R8G8B8, core::dimension2d<u32>(tex[i].width, tex[i].height)); |
1036 | 1036 | ||
1037 | CColorConverter::convert8BitTo24Bit(src, (u8*)image->lock(), tex[i].width, tex[i].height, (u8*) palette, 0, false); | 1037 | CColorConverter::convert8BitTo24Bit(src, (u8*)image->lock(), tex[i].width, tex[i].height, (u8*) palette, 0, false); |
1038 | image->unlock(); | 1038 | image->unlock(); |
1039 | 1039 | ||
1040 | #ifdef HL_TEXTURE_ATLAS | 1040 | #ifdef HL_TEXTURE_ATLAS |
1041 | TextureAtlas.addSource ( tex[i].name, image ); | 1041 | TextureAtlas.addSource ( tex[i].name, image ); |
1042 | #else | 1042 | #else |
1043 | core::splitFilename ( tex[i].name, 0, &fname, &ext ); | 1043 | core::splitFilename ( tex[i].name, 0, &fname, &ext ); |
1044 | SceneManager->getVideoDriver()->addTexture ( TextureBaseName + fname, image ); | 1044 | SceneManager->getVideoDriver()->addTexture ( TextureBaseName + fname, image ); |
1045 | image->drop(); | 1045 | image->drop(); |
1046 | #endif | 1046 | #endif |
1047 | } | 1047 | } |
1048 | delete [] palette; | 1048 | delete [] palette; |
1049 | 1049 | ||
1050 | #ifdef HL_TEXTURE_ATLAS | 1050 | #ifdef HL_TEXTURE_ATLAS |
1051 | TextureAtlas.create ( 2 * 2 + 1, ETC_CLAMP ); | 1051 | TextureAtlas.create ( 2 * 2 + 1, ETC_CLAMP ); |
1052 | SceneManager->getVideoDriver()->addTexture ( TextureBaseName + "atlas", TextureAtlas.Master ); | 1052 | SceneManager->getVideoDriver()->addTexture ( TextureBaseName + "atlas", TextureAtlas.Master ); |
1053 | TextureAtlas.release(); | 1053 | TextureAtlas.release(); |
1054 | #endif | 1054 | #endif |
1055 | } | 1055 | } |
1056 | 1056 | ||
1057 | if (!Header) | 1057 | if (!Header) |
1058 | Header = header; | 1058 | Header = header; |
1059 | 1059 | ||
1060 | if ( closefile ) | 1060 | if ( closefile ) |
1061 | { | 1061 | { |
1062 | file->drop(); | 1062 | file->drop(); |
1063 | file = 0; | 1063 | file = 0; |
1064 | } | 1064 | } |
1065 | 1065 | ||
1066 | return header; | 1066 | return header; |
1067 | } | 1067 | } |
1068 | 1068 | ||
1069 | 1069 | ||
1070 | /*! | 1070 | /*! |
1071 | */ | 1071 | */ |
1072 | f32 CAnimatedMeshHalfLife::SetController( s32 controllerIndex, f32 value ) | 1072 | f32 CAnimatedMeshHalfLife::SetController( s32 controllerIndex, f32 value ) |
1073 | { | 1073 | { |
1074 | if (!Header) | 1074 | if (!Header) |
1075 | return 0.f; | 1075 | return 0.f; |
1076 | 1076 | ||
1077 | SHalflifeBoneController *bonecontroller = (SHalflifeBoneController *)((u8*) Header + Header->bonecontrollerindex); | 1077 | SHalflifeBoneController *bonecontroller = (SHalflifeBoneController *)((u8*) Header + Header->bonecontrollerindex); |
1078 | 1078 | ||
1079 | // find first controller that matches the index | 1079 | // find first controller that matches the index |
1080 | u32 i; | 1080 | u32 i; |
1081 | for (i = 0; i < Header->numbonecontrollers; i++, bonecontroller++) | 1081 | for (i = 0; i < Header->numbonecontrollers; i++, bonecontroller++) |
1082 | { | 1082 | { |
1083 | if (bonecontroller->index == controllerIndex) | 1083 | if (bonecontroller->index == controllerIndex) |
1084 | break; | 1084 | break; |
1085 | } | 1085 | } |
1086 | if (i >= Header->numbonecontrollers) | 1086 | if (i >= Header->numbonecontrollers) |
1087 | return value; | 1087 | return value; |
1088 | 1088 | ||
1089 | // wrap 0..360 if it's a rotational controller | 1089 | // wrap 0..360 if it's a rotational controller |
1090 | if (bonecontroller->type & (STUDIO_XR | STUDIO_YR | STUDIO_ZR)) | 1090 | if (bonecontroller->type & (STUDIO_XR | STUDIO_YR | STUDIO_ZR)) |
1091 | { | 1091 | { |
1092 | // ugly hack, invert value if end < start | 1092 | // ugly hack, invert value if end < start |
1093 | if (bonecontroller->end < bonecontroller->start) | 1093 | if (bonecontroller->end < bonecontroller->start) |
1094 | value = -value; | 1094 | value = -value; |
1095 | 1095 | ||
1096 | // does the controller not wrap? | 1096 | // does the controller not wrap? |
1097 | if (bonecontroller->start + 359.f >= bonecontroller->end) | 1097 | if (bonecontroller->start + 359.f >= bonecontroller->end) |
1098 | { | 1098 | { |
1099 | if (value > ((bonecontroller->start + bonecontroller->end) / 2.f) + 180.f) | 1099 | if (value > ((bonecontroller->start + bonecontroller->end) / 2.f) + 180.f) |
1100 | value = value - 360.f; | 1100 | value = value - 360.f; |
1101 | if (value < ((bonecontroller->start + bonecontroller->end) / 2.f) - 180.f) | 1101 | if (value < ((bonecontroller->start + bonecontroller->end) / 2.f) - 180.f) |
1102 | value = value + 360.f; | 1102 | value = value + 360.f; |
1103 | } | 1103 | } |
1104 | else | 1104 | else |
1105 | { | 1105 | { |
1106 | if (value > 360.f) | 1106 | if (value > 360.f) |
1107 | value = value - (s32)(value / 360.f) * 360.f; | 1107 | value = value - (s32)(value / 360.f) * 360.f; |
1108 | else if (value < 0.f) | 1108 | else if (value < 0.f) |
1109 | value = value + (s32)((value / -360.f) + 1) * 360.f; | 1109 | value = value + (s32)((value / -360.f) + 1) * 360.f; |
1110 | } | 1110 | } |
1111 | } | 1111 | } |
1112 | 1112 | ||
1113 | s32 range = controllerIndex == MOUTH_CONTROLLER ? 64 : 255; | 1113 | s32 range = controllerIndex == MOUTH_CONTROLLER ? 64 : 255; |
1114 | 1114 | ||
1115 | s32 setting = (s32) ( (f32) range * (value - bonecontroller->start) / (bonecontroller->end - bonecontroller->start)); | 1115 | s32 setting = (s32) ( (f32) range * (value - bonecontroller->start) / (bonecontroller->end - bonecontroller->start)); |
1116 | 1116 | ||
1117 | if (setting < 0) setting = 0; | 1117 | if (setting < 0) setting = 0; |
1118 | if (setting > range) setting = range; | 1118 | if (setting > range) setting = range; |
1119 | 1119 | ||
1120 | BoneController[controllerIndex] = setting; | 1120 | BoneController[controllerIndex] = setting; |
1121 | 1121 | ||
1122 | return setting * (1.f / (f32) range ) * (bonecontroller->end - bonecontroller->start) + bonecontroller->start; | 1122 | return setting * (1.f / (f32) range ) * (bonecontroller->end - bonecontroller->start) + bonecontroller->start; |
1123 | } | 1123 | } |
1124 | 1124 | ||
1125 | 1125 | ||
1126 | /*! | 1126 | /*! |
1127 | */ | 1127 | */ |
1128 | u32 CAnimatedMeshHalfLife::SetSkin( u32 value ) | 1128 | u32 CAnimatedMeshHalfLife::SetSkin( u32 value ) |
1129 | { | 1129 | { |
1130 | if (value < Header->numskinfamilies) | 1130 | if (value < Header->numskinfamilies) |
1131 | SkinGroupSelection = value; | 1131 | SkinGroupSelection = value; |
1132 | 1132 | ||
1133 | return SkinGroupSelection; | 1133 | return SkinGroupSelection; |
1134 | } | 1134 | } |
1135 | 1135 | ||
1136 | 1136 | ||
1137 | /*! | 1137 | /*! |
1138 | */ | 1138 | */ |
1139 | bool CAnimatedMeshHalfLife::postLoadModel( const io::path &filename ) | 1139 | bool CAnimatedMeshHalfLife::postLoadModel( const io::path &filename ) |
1140 | { | 1140 | { |
1141 | io::path path; | 1141 | io::path path; |
1142 | io::path texname; | 1142 | io::path texname; |
1143 | io::path submodel; | 1143 | io::path submodel; |
1144 | 1144 | ||
1145 | core::splitFilename ( filename ,&path, &texname, 0 ); | 1145 | core::splitFilename ( filename ,&path, &texname, 0 ); |
1146 | 1146 | ||
1147 | // preload textures | 1147 | // preload textures |
1148 | // if no textures are stored in main file, use texfile | 1148 | // if no textures are stored in main file, use texfile |
1149 | if (Header->numtextures == 0) | 1149 | if (Header->numtextures == 0) |
1150 | { | 1150 | { |
1151 | submodel = path + texname + "T.mdl"; | 1151 | submodel = path + texname + "T.mdl"; |
1152 | TextureHeader = loadModel(0, submodel); | 1152 | TextureHeader = loadModel(0, submodel); |
1153 | if (!TextureHeader) | 1153 | if (!TextureHeader) |
1154 | return false; | 1154 | return false; |
1155 | OwnTexModel = true; | 1155 | OwnTexModel = true; |
1156 | } | 1156 | } |
1157 | else | 1157 | else |
1158 | { | 1158 | { |
1159 | TextureHeader = Header; | 1159 | TextureHeader = Header; |
1160 | OwnTexModel = false; | 1160 | OwnTexModel = false; |
1161 | } | 1161 | } |
1162 | 1162 | ||
1163 | // preload animations | 1163 | // preload animations |
1164 | if (Header->numseqgroups > 1) | 1164 | if (Header->numseqgroups > 1) |
1165 | { | 1165 | { |
1166 | c8 seq[8]; | 1166 | c8 seq[8]; |
1167 | for (u32 i = 1; i < Header->numseqgroups; i++) | 1167 | for (u32 i = 1; i < Header->numseqgroups; i++) |
1168 | { | 1168 | { |
1169 | snprintf( seq, 8, "%02d.mdl", i ); | 1169 | snprintf( seq, 8, "%02d.mdl", i ); |
1170 | submodel = path + texname + seq; | 1170 | submodel = path + texname + seq; |
1171 | 1171 | ||
1172 | AnimationHeader[i] = loadModel(0, submodel); | 1172 | AnimationHeader[i] = loadModel(0, submodel); |
1173 | if (!AnimationHeader[i]) | 1173 | if (!AnimationHeader[i]) |
1174 | return false; | 1174 | return false; |
1175 | } | 1175 | } |
1176 | } | 1176 | } |
1177 | 1177 | ||
1178 | return true; | 1178 | return true; |
1179 | } | 1179 | } |
1180 | 1180 | ||
1181 | 1181 | ||
1182 | /*! | 1182 | /*! |
1183 | */ | 1183 | */ |
1184 | void CAnimatedMeshHalfLife::dumpModelInfo(u32 level) const | 1184 | void CAnimatedMeshHalfLife::dumpModelInfo(u32 level) const |
1185 | { | 1185 | { |
1186 | const u8 *phdr = (const u8*) Header; | 1186 | const u8 *phdr = (const u8*) Header; |
1187 | const SHalflifeHeader * hdr = Header; | 1187 | const SHalflifeHeader * hdr = Header; |
1188 | u32 i; | 1188 | u32 i; |
1189 | 1189 | ||
1190 | if (level == 0) | 1190 | if (level == 0) |
1191 | { | 1191 | { |
1192 | printf ( | 1192 | printf ( |
1193 | "Bones: %d\n" | 1193 | "Bones: %d\n" |
1194 | "Bone Controllers: %d\n" | 1194 | "Bone Controllers: %d\n" |
1195 | "Hit Boxes: %d\n" | 1195 | "Hit Boxes: %d\n" |
1196 | "Sequences: %d\n" | 1196 | "Sequences: %d\n" |
1197 | "Sequence Groups: %d\n", | 1197 | "Sequence Groups: %d\n", |
1198 | hdr->numbones, | 1198 | hdr->numbones, |
1199 | hdr->numbonecontrollers, | 1199 | hdr->numbonecontrollers, |
1200 | hdr->numhitboxes, | 1200 | hdr->numhitboxes, |
1201 | hdr->numseq, | 1201 | hdr->numseq, |
1202 | hdr->numseqgroups | 1202 | hdr->numseqgroups |
1203 | ); | 1203 | ); |
1204 | printf ( | 1204 | printf ( |
1205 | "Textures: %d\n" | 1205 | "Textures: %d\n" |
1206 | "Skin Families: %d\n" | 1206 | "Skin Families: %d\n" |
1207 | "Bodyparts: %d\n" | 1207 | "Bodyparts: %d\n" |
1208 | "Attachments: %d\n" | 1208 | "Attachments: %d\n" |
1209 | "Transitions: %d\n", | 1209 | "Transitions: %d\n", |
1210 | hdr->numtextures, | 1210 | hdr->numtextures, |
1211 | hdr->numskinfamilies, | 1211 | hdr->numskinfamilies, |
1212 | hdr->numbodyparts, | 1212 | hdr->numbodyparts, |
1213 | hdr->numattachments, | 1213 | hdr->numattachments, |
1214 | hdr->numtransitions); | 1214 | hdr->numtransitions); |
1215 | return; | 1215 | return; |
1216 | } | 1216 | } |
1217 | 1217 | ||
1218 | printf("id: %c%c%c%c\n", phdr[0], phdr[1], phdr[2], phdr[3]); | 1218 | printf("id: %c%c%c%c\n", phdr[0], phdr[1], phdr[2], phdr[3]); |
1219 | printf("version: %d\n", hdr->version); | 1219 | printf("version: %d\n", hdr->version); |
1220 | printf("name: \"%s\"\n", hdr->name); | 1220 | printf("name: \"%s\"\n", hdr->name); |
1221 | printf("length: %d\n\n", hdr->length); | 1221 | printf("length: %d\n\n", hdr->length); |
1222 | 1222 | ||
1223 | printf("eyeposition: %f %f %f\n", hdr->eyeposition[0], hdr->eyeposition[1], hdr->eyeposition[2]); | 1223 | printf("eyeposition: %f %f %f\n", hdr->eyeposition[0], hdr->eyeposition[1], hdr->eyeposition[2]); |
1224 | printf("min: %f %f %f\n", hdr->min[0], hdr->min[1], hdr->min[2]); | 1224 | printf("min: %f %f %f\n", hdr->min[0], hdr->min[1], hdr->min[2]); |
1225 | printf("max: %f %f %f\n", hdr->max[0], hdr->max[1], hdr->max[2]); | 1225 | printf("max: %f %f %f\n", hdr->max[0], hdr->max[1], hdr->max[2]); |
1226 | printf("bbmin: %f %f %f\n", hdr->bbmin[0], hdr->bbmin[1], hdr->bbmin[2]); | 1226 | printf("bbmin: %f %f %f\n", hdr->bbmin[0], hdr->bbmin[1], hdr->bbmin[2]); |
1227 | printf("bbmax: %f %f %f\n", hdr->bbmax[0], hdr->bbmax[1], hdr->bbmax[2]); | 1227 | printf("bbmax: %f %f %f\n", hdr->bbmax[0], hdr->bbmax[1], hdr->bbmax[2]); |
1228 | 1228 | ||
1229 | printf("flags: %d\n\n", hdr->flags); | 1229 | printf("flags: %d\n\n", hdr->flags); |
1230 | 1230 | ||
1231 | printf("numbones: %d\n", hdr->numbones); | 1231 | printf("numbones: %d\n", hdr->numbones); |
1232 | for (i = 0; i < hdr->numbones; i++) | 1232 | for (i = 0; i < hdr->numbones; i++) |
1233 | { | 1233 | { |
1234 | const SHalflifeBone *bone = (const SHalflifeBone *) (phdr + hdr->boneindex); | 1234 | const SHalflifeBone *bone = (const SHalflifeBone *) (phdr + hdr->boneindex); |
1235 | printf("bone %d.name: \"%s\"\n", i + 1, bone[i].name); | 1235 | printf("bone %d.name: \"%s\"\n", i + 1, bone[i].name); |
1236 | printf("bone %d.parent: %d\n", i + 1, bone[i].parent); | 1236 | printf("bone %d.parent: %d\n", i + 1, bone[i].parent); |
1237 | printf("bone %d.flags: %d\n", i + 1, bone[i].flags); | 1237 | printf("bone %d.flags: %d\n", i + 1, bone[i].flags); |
1238 | printf("bone %d.bonecontroller: %d %d %d %d %d %d\n", i + 1, bone[i].bonecontroller[0], bone[i].bonecontroller[1], bone[i].bonecontroller[2], bone[i].bonecontroller[3], bone[i].bonecontroller[4], bone[i].bonecontroller[5]); | 1238 | printf("bone %d.bonecontroller: %d %d %d %d %d %d\n", i + 1, bone[i].bonecontroller[0], bone[i].bonecontroller[1], bone[i].bonecontroller[2], bone[i].bonecontroller[3], bone[i].bonecontroller[4], bone[i].bonecontroller[5]); |
1239 | printf("bone %d.value: %f %f %f %f %f %f\n", i + 1, bone[i].value[0], bone[i].value[1], bone[i].value[2], bone[i].value[3], bone[i].value[4], bone[i].value[5]); | 1239 | printf("bone %d.value: %f %f %f %f %f %f\n", i + 1, bone[i].value[0], bone[i].value[1], bone[i].value[2], bone[i].value[3], bone[i].value[4], bone[i].value[5]); |
1240 | printf("bone %d.scale: %f %f %f %f %f %f\n", i + 1, bone[i].scale[0], bone[i].scale[1], bone[i].scale[2], bone[i].scale[3], bone[i].scale[4], bone[i].scale[5]); | 1240 | printf("bone %d.scale: %f %f %f %f %f %f\n", i + 1, bone[i].scale[0], bone[i].scale[1], bone[i].scale[2], bone[i].scale[3], bone[i].scale[4], bone[i].scale[5]); |
1241 | } | 1241 | } |
1242 | 1242 | ||
1243 | printf("\nnumbonecontrollers: %d\n", hdr->numbonecontrollers); | 1243 | printf("\nnumbonecontrollers: %d\n", hdr->numbonecontrollers); |
1244 | const SHalflifeBoneController *bonecontrollers = (const SHalflifeBoneController *) (phdr + hdr->bonecontrollerindex); | 1244 | const SHalflifeBoneController *bonecontrollers = (const SHalflifeBoneController *) (phdr + hdr->bonecontrollerindex); |
1245 | for (i = 0; i < hdr->numbonecontrollers; i++) | 1245 | for (i = 0; i < hdr->numbonecontrollers; i++) |
1246 | { | 1246 | { |
1247 | printf("bonecontroller %d.bone: %d\n", i + 1, bonecontrollers[i].bone); | 1247 | printf("bonecontroller %d.bone: %d\n", i + 1, bonecontrollers[i].bone); |
1248 | printf("bonecontroller %d.type: %d\n", i + 1, bonecontrollers[i].type); | 1248 | printf("bonecontroller %d.type: %d\n", i + 1, bonecontrollers[i].type); |
1249 | printf("bonecontroller %d.start: %f\n", i + 1, bonecontrollers[i].start); | 1249 | printf("bonecontroller %d.start: %f\n", i + 1, bonecontrollers[i].start); |
1250 | printf("bonecontroller %d.end: %f\n", i + 1, bonecontrollers[i].end); | 1250 | printf("bonecontroller %d.end: %f\n", i + 1, bonecontrollers[i].end); |
1251 | printf("bonecontroller %d.rest: %d\n", i + 1, bonecontrollers[i].rest); | 1251 | printf("bonecontroller %d.rest: %d\n", i + 1, bonecontrollers[i].rest); |
1252 | printf("bonecontroller %d.index: %d\n", i + 1, bonecontrollers[i].index); | 1252 | printf("bonecontroller %d.index: %d\n", i + 1, bonecontrollers[i].index); |
1253 | } | 1253 | } |
1254 | 1254 | ||
1255 | printf("\nnumhitboxes: %d\n", hdr->numhitboxes); | 1255 | printf("\nnumhitboxes: %d\n", hdr->numhitboxes); |
1256 | const SHalflifeBBox *box = (const SHalflifeBBox *) (phdr + hdr->hitboxindex); | 1256 | const SHalflifeBBox *box = (const SHalflifeBBox *) (phdr + hdr->hitboxindex); |
1257 | for (i = 0; i < hdr->numhitboxes; i++) | 1257 | for (i = 0; i < hdr->numhitboxes; i++) |
1258 | { | 1258 | { |
1259 | printf("hitbox %d.bone: %d\n", i + 1, box[i].bone); | 1259 | printf("hitbox %d.bone: %d\n", i + 1, box[i].bone); |
1260 | printf("hitbox %d.group: %d\n", i + 1, box[i].group); | 1260 | printf("hitbox %d.group: %d\n", i + 1, box[i].group); |
1261 | printf("hitbox %d.bbmin: %f %f %f\n", i + 1, box[i].bbmin[0], box[i].bbmin[1], box[i].bbmin[2]); | 1261 | printf("hitbox %d.bbmin: %f %f %f\n", i + 1, box[i].bbmin[0], box[i].bbmin[1], box[i].bbmin[2]); |
1262 | printf("hitbox %d.bbmax: %f %f %f\n", i + 1, box[i].bbmax[0], box[i].bbmax[1], box[i].bbmax[2]); | 1262 | printf("hitbox %d.bbmax: %f %f %f\n", i + 1, box[i].bbmax[0], box[i].bbmax[1], box[i].bbmax[2]); |
1263 | } | 1263 | } |
1264 | 1264 | ||
1265 | printf("\nnumseq: %d\n", hdr->numseq); | 1265 | printf("\nnumseq: %d\n", hdr->numseq); |
1266 | const SHalflifeSequence *seq = (const SHalflifeSequence *) (phdr + hdr->seqindex); | 1266 | const SHalflifeSequence *seq = (const SHalflifeSequence *) (phdr + hdr->seqindex); |
1267 | for (i = 0; i < hdr->numseq; i++) | 1267 | for (i = 0; i < hdr->numseq; i++) |
1268 | { | 1268 | { |
1269 | printf("seqdesc %d.label: \"%s\"\n", i + 1, seq[i].label); | 1269 | printf("seqdesc %d.label: \"%s\"\n", i + 1, seq[i].label); |
1270 | printf("seqdesc %d.fps: %f\n", i + 1, seq[i].fps); | 1270 | printf("seqdesc %d.fps: %f\n", i + 1, seq[i].fps); |
1271 | printf("seqdesc %d.flags: %d\n", i + 1, seq[i].flags); | 1271 | printf("seqdesc %d.flags: %d\n", i + 1, seq[i].flags); |
1272 | printf("<...>\n"); | 1272 | printf("<...>\n"); |
1273 | } | 1273 | } |
1274 | 1274 | ||
1275 | printf("\nnumseqgroups: %d\n", hdr->numseqgroups); | 1275 | printf("\nnumseqgroups: %d\n", hdr->numseqgroups); |
1276 | for (i = 0; i < hdr->numseqgroups; i++) | 1276 | for (i = 0; i < hdr->numseqgroups; i++) |
1277 | { | 1277 | { |
1278 | const SHalflifeSequenceGroup *group = (const SHalflifeSequenceGroup *) (phdr + hdr->seqgroupindex); | 1278 | const SHalflifeSequenceGroup *group = (const SHalflifeSequenceGroup *) (phdr + hdr->seqgroupindex); |
1279 | printf("\nseqgroup %d.label: \"%s\"\n", i + 1, group[i].label); | 1279 | printf("\nseqgroup %d.label: \"%s\"\n", i + 1, group[i].label); |
1280 | printf("\nseqgroup %d.namel: \"%s\"\n", i + 1, group[i].name); | 1280 | printf("\nseqgroup %d.namel: \"%s\"\n", i + 1, group[i].name); |
1281 | printf("\nseqgroup %d.data: %d\n", i + 1, group[i].data); | 1281 | printf("\nseqgroup %d.data: %d\n", i + 1, group[i].data); |
1282 | } | 1282 | } |
1283 | 1283 | ||
1284 | printf("\nnumskinref: %d\n", hdr->numskinref); | 1284 | printf("\nnumskinref: %d\n", hdr->numskinref); |
1285 | printf("numskinfamilies: %d\n", hdr->numskinfamilies); | 1285 | printf("numskinfamilies: %d\n", hdr->numskinfamilies); |
1286 | 1286 | ||
1287 | printf("\nnumbodyparts: %d\n", hdr->numbodyparts); | 1287 | printf("\nnumbodyparts: %d\n", hdr->numbodyparts); |
1288 | const SHalflifeBody *pbodyparts = (const SHalflifeBody*) ((const u8*) hdr + hdr->bodypartindex); | 1288 | const SHalflifeBody *pbodyparts = (const SHalflifeBody*) ((const u8*) hdr + hdr->bodypartindex); |
1289 | for (i = 0; i < hdr->numbodyparts; i++) | 1289 | for (i = 0; i < hdr->numbodyparts; i++) |
1290 | { | 1290 | { |
1291 | printf("bodypart %d.name: \"%s\"\n", i + 1, pbodyparts[i].name); | 1291 | printf("bodypart %d.name: \"%s\"\n", i + 1, pbodyparts[i].name); |
1292 | printf("bodypart %d.nummodels: %d\n", i + 1, pbodyparts[i].nummodels); | 1292 | printf("bodypart %d.nummodels: %d\n", i + 1, pbodyparts[i].nummodels); |
1293 | printf("bodypart %d.base: %d\n", i + 1, pbodyparts[i].base); | 1293 | printf("bodypart %d.base: %d\n", i + 1, pbodyparts[i].base); |
1294 | printf("bodypart %d.modelindex: %d\n", i + 1, pbodyparts[i].modelindex); | 1294 | printf("bodypart %d.modelindex: %d\n", i + 1, pbodyparts[i].modelindex); |
1295 | } | 1295 | } |
1296 | 1296 | ||
1297 | printf("\nnumattachments: %d\n", hdr->numattachments); | 1297 | printf("\nnumattachments: %d\n", hdr->numattachments); |
1298 | for (i = 0; i < hdr->numattachments; i++) | 1298 | for (i = 0; i < hdr->numattachments; i++) |
1299 | { | 1299 | { |
1300 | const SHalflifeAttachment *attach = (const SHalflifeAttachment *) ((const u8*) hdr + hdr->attachmentindex); | 1300 | const SHalflifeAttachment *attach = (const SHalflifeAttachment *) ((const u8*) hdr + hdr->attachmentindex); |
1301 | printf("attachment %d.name: \"%s\"\n", i + 1, attach[i].name); | 1301 | printf("attachment %d.name: \"%s\"\n", i + 1, attach[i].name); |
1302 | } | 1302 | } |
1303 | 1303 | ||
1304 | hdr = TextureHeader; | 1304 | hdr = TextureHeader; |
1305 | printf("\nnumtextures: %d\n", hdr->numtextures); | 1305 | printf("\nnumtextures: %d\n", hdr->numtextures); |
1306 | printf("textureindex: %d\n", hdr->textureindex); | 1306 | printf("textureindex: %d\n", hdr->textureindex); |
1307 | printf("texturedataindex: %d\n", hdr->texturedataindex); | 1307 | printf("texturedataindex: %d\n", hdr->texturedataindex); |
1308 | const SHalflifeTexture *ptextures = (const SHalflifeTexture *) ((const u8*) hdr + hdr->textureindex); | 1308 | const SHalflifeTexture *ptextures = (const SHalflifeTexture *) ((const u8*) hdr + hdr->textureindex); |
1309 | for (i = 0; i < hdr->numtextures; i++) | 1309 | for (i = 0; i < hdr->numtextures; i++) |
1310 | { | 1310 | { |
1311 | printf("texture %d.name: \"%s\"\n", i + 1, ptextures[i].name); | 1311 | printf("texture %d.name: \"%s\"\n", i + 1, ptextures[i].name); |
1312 | printf("texture %d.flags: %d\n", i + 1, ptextures[i].flags); | 1312 | printf("texture %d.flags: %d\n", i + 1, ptextures[i].flags); |
1313 | printf("texture %d.width: %d\n", i + 1, ptextures[i].width); | 1313 | printf("texture %d.width: %d\n", i + 1, ptextures[i].width); |
1314 | printf("texture %d.height: %d\n", i + 1, ptextures[i].height); | 1314 | printf("texture %d.height: %d\n", i + 1, ptextures[i].height); |
1315 | printf("texture %d.index: %d\n", i + 1, ptextures[i].index); | 1315 | printf("texture %d.index: %d\n", i + 1, ptextures[i].index); |
1316 | } | 1316 | } |
1317 | } | 1317 | } |
1318 | 1318 | ||
1319 | 1319 | ||
1320 | /*! | 1320 | /*! |
1321 | */ | 1321 | */ |
1322 | void CAnimatedMeshHalfLife::ExtractBbox(s32 sequence, core::aabbox3df &box) const | 1322 | void CAnimatedMeshHalfLife::ExtractBbox(s32 sequence, core::aabbox3df &box) const |
1323 | { | 1323 | { |
1324 | const SHalflifeSequence *seq = (const SHalflifeSequence *)((const u8*)Header + Header->seqindex) + sequence; | 1324 | const SHalflifeSequence *seq = (const SHalflifeSequence *)((const u8*)Header + Header->seqindex) + sequence; |
1325 | 1325 | ||
1326 | box.MinEdge.X = seq[0].bbmin[0]; | 1326 | box.MinEdge.X = seq[0].bbmin[0]; |
1327 | box.MinEdge.Y = seq[0].bbmin[1]; | 1327 | box.MinEdge.Y = seq[0].bbmin[1]; |
1328 | box.MinEdge.Z = seq[0].bbmin[2]; | 1328 | box.MinEdge.Z = seq[0].bbmin[2]; |
1329 | 1329 | ||
1330 | box.MaxEdge.X = seq[0].bbmax[0]; | 1330 | box.MaxEdge.X = seq[0].bbmax[0]; |
1331 | box.MaxEdge.Y = seq[0].bbmax[1]; | 1331 | box.MaxEdge.Y = seq[0].bbmax[1]; |
1332 | box.MaxEdge.Z = seq[0].bbmax[2]; | 1332 | box.MaxEdge.Z = seq[0].bbmax[2]; |
1333 | } | 1333 | } |
1334 | 1334 | ||
1335 | 1335 | ||
1336 | /*! | 1336 | /*! |
1337 | */ | 1337 | */ |
1338 | void CAnimatedMeshHalfLife::calcBoneAdj() | 1338 | void CAnimatedMeshHalfLife::calcBoneAdj() |
1339 | { | 1339 | { |
1340 | const SHalflifeBoneController *bonecontroller = | 1340 | const SHalflifeBoneController *bonecontroller = |
1341 | (const SHalflifeBoneController *)((const u8*) Header + Header->bonecontrollerindex); | 1341 | (const SHalflifeBoneController *)((const u8*) Header + Header->bonecontrollerindex); |
1342 | 1342 | ||
1343 | for (u32 j = 0; j < Header->numbonecontrollers; j++) | 1343 | for (u32 j = 0; j < Header->numbonecontrollers; j++) |
1344 | { | 1344 | { |
1345 | const s32 i = bonecontroller[j].index; | 1345 | const s32 i = bonecontroller[j].index; |
1346 | // check for 360% wrapping | 1346 | // check for 360% wrapping |
1347 | f32 value; | 1347 | f32 value; |
1348 | if (bonecontroller[j].type & STUDIO_RLOOP) | 1348 | if (bonecontroller[j].type & STUDIO_RLOOP) |
1349 | { | 1349 | { |
1350 | value = BoneController[i] * (360.f/256.f) + bonecontroller[j].start; | 1350 | value = BoneController[i] * (360.f/256.f) + bonecontroller[j].start; |
1351 | } | 1351 | } |
1352 | else | 1352 | else |
1353 | { | 1353 | { |
1354 | const f32 range = i <= 3 ? 255.f : 64.f; | 1354 | const f32 range = i <= 3 ? 255.f : 64.f; |
1355 | value = core::clamp(BoneController[i] / range,0.f,1.f); | 1355 | value = core::clamp(BoneController[i] / range,0.f,1.f); |
1356 | value = (1.f - value) * bonecontroller[j].start + value * bonecontroller[j].end; | 1356 | value = (1.f - value) * bonecontroller[j].start + value * bonecontroller[j].end; |
1357 | } | 1357 | } |
1358 | 1358 | ||
1359 | switch(bonecontroller[j].type & STUDIO_TYPES) | 1359 | switch(bonecontroller[j].type & STUDIO_TYPES) |
1360 | { | 1360 | { |
1361 | case STUDIO_XR: | 1361 | case STUDIO_XR: |
1362 | case STUDIO_YR: | 1362 | case STUDIO_YR: |
1363 | case STUDIO_ZR: | 1363 | case STUDIO_ZR: |
1364 | BoneAdj[j] = value * core::DEGTORAD; | 1364 | BoneAdj[j] = value * core::DEGTORAD; |
1365 | break; | 1365 | break; |
1366 | case STUDIO_X: | 1366 | case STUDIO_X: |
1367 | case STUDIO_Y: | 1367 | case STUDIO_Y: |
1368 | case STUDIO_Z: | 1368 | case STUDIO_Z: |
1369 | BoneAdj[j] = value; | 1369 | BoneAdj[j] = value; |
1370 | break; | 1370 | break; |
1371 | } | 1371 | } |
1372 | } | 1372 | } |
1373 | } | 1373 | } |
1374 | 1374 | ||
1375 | 1375 | ||
1376 | /*! | 1376 | /*! |
1377 | */ | 1377 | */ |
1378 | void CAnimatedMeshHalfLife::calcBoneQuaternion(const s32 frame, const SHalflifeBone * const bone, | 1378 | void CAnimatedMeshHalfLife::calcBoneQuaternion(const s32 frame, const SHalflifeBone * const bone, |
1379 | SHalflifeAnimOffset *anim, const u32 j, f32& angle1, f32& angle2) const | 1379 | SHalflifeAnimOffset *anim, const u32 j, f32& angle1, f32& angle2) const |
1380 | { | 1380 | { |
1381 | // three vector components | 1381 | // three vector components |
1382 | if (anim->offset[j+3] == 0) | 1382 | if (anim->offset[j+3] == 0) |
1383 | { | 1383 | { |
1384 | angle2 = angle1 = bone->value[j+3]; // default | 1384 | angle2 = angle1 = bone->value[j+3]; // default |
1385 | } | 1385 | } |
1386 | else | 1386 | else |
1387 | { | 1387 | { |
1388 | SHalflifeAnimationFrame *animvalue = (SHalflifeAnimationFrame *)((u8*)anim + anim->offset[j+3]); | 1388 | SHalflifeAnimationFrame *animvalue = (SHalflifeAnimationFrame *)((u8*)anim + anim->offset[j+3]); |
1389 | s32 k = frame; | 1389 | s32 k = frame; |
1390 | while (animvalue->num.total <= k) | 1390 | while (animvalue->num.total <= k) |
1391 | { | 1391 | { |
1392 | k -= animvalue->num.total; | 1392 | k -= animvalue->num.total; |
1393 | animvalue += animvalue->num.valid + 1; | 1393 | animvalue += animvalue->num.valid + 1; |
1394 | } | 1394 | } |
1395 | // Bah, missing blend! | 1395 | // Bah, missing blend! |
1396 | if (animvalue->num.valid > k) | 1396 | if (animvalue->num.valid > k) |
1397 | { | 1397 | { |
1398 | angle1 = animvalue[k+1].value; | 1398 | angle1 = animvalue[k+1].value; |
1399 | 1399 | ||
1400 | if (animvalue->num.valid > k + 1) | 1400 | if (animvalue->num.valid > k + 1) |
1401 | { | 1401 | { |
1402 | angle2 = animvalue[k+2].value; | 1402 | angle2 = animvalue[k+2].value; |
1403 | } | 1403 | } |
1404 | else | 1404 | else |
1405 | { | 1405 | { |
1406 | if (animvalue->num.total > k + 1) | 1406 | if (animvalue->num.total > k + 1) |
1407 | angle2 = angle1; | 1407 | angle2 = angle1; |
1408 | else | 1408 | else |
1409 | angle2 = animvalue[animvalue->num.valid+2].value; | 1409 | angle2 = animvalue[animvalue->num.valid+2].value; |
1410 | } | 1410 | } |
1411 | } | 1411 | } |
1412 | else | 1412 | else |
1413 | { | 1413 | { |
1414 | angle1 = animvalue[animvalue->num.valid].value; | 1414 | angle1 = animvalue[animvalue->num.valid].value; |
1415 | if (animvalue->num.total > k + 1) | 1415 | if (animvalue->num.total > k + 1) |
1416 | { | 1416 | { |
1417 | angle2 = angle1; | 1417 | angle2 = angle1; |
1418 | } | 1418 | } |
1419 | else | 1419 | else |
1420 | { | 1420 | { |
1421 | angle2 = animvalue[animvalue->num.valid + 2].value; | 1421 | angle2 = animvalue[animvalue->num.valid + 2].value; |
1422 | } | 1422 | } |
1423 | } | 1423 | } |
1424 | angle1 = bone->value[j+3] + angle1 * bone->scale[j+3]; | 1424 | angle1 = bone->value[j+3] + angle1 * bone->scale[j+3]; |
1425 | angle2 = bone->value[j+3] + angle2 * bone->scale[j+3]; | 1425 | angle2 = bone->value[j+3] + angle2 * bone->scale[j+3]; |
1426 | } | 1426 | } |
1427 | 1427 | ||
1428 | if (bone->bonecontroller[j+3] != -1) | 1428 | if (bone->bonecontroller[j+3] != -1) |
1429 | { | 1429 | { |
1430 | angle1 += BoneAdj[bone->bonecontroller[j+3]]; | 1430 | angle1 += BoneAdj[bone->bonecontroller[j+3]]; |
1431 | angle2 += BoneAdj[bone->bonecontroller[j+3]]; | 1431 | angle2 += BoneAdj[bone->bonecontroller[j+3]]; |
1432 | } | 1432 | } |
1433 | } | 1433 | } |
1434 | 1434 | ||
1435 | 1435 | ||
1436 | /*! | 1436 | /*! |
1437 | */ | 1437 | */ |
1438 | void CAnimatedMeshHalfLife::calcBonePosition(const s32 frame, f32 s, | 1438 | void CAnimatedMeshHalfLife::calcBonePosition(const s32 frame, f32 s, |
1439 | const SHalflifeBone * const bone, SHalflifeAnimOffset *anim, f32 *pos) const | 1439 | const SHalflifeBone * const bone, SHalflifeAnimOffset *anim, f32 *pos) const |
1440 | { | 1440 | { |
1441 | for (s32 j = 0; j < 3; ++j) | 1441 | for (s32 j = 0; j < 3; ++j) |
1442 | { | 1442 | { |
1443 | pos[j] = bone->value[j]; // default; | 1443 | pos[j] = bone->value[j]; // default; |
1444 | if (anim->offset[j] != 0) | 1444 | if (anim->offset[j] != 0) |
1445 | { | 1445 | { |
1446 | SHalflifeAnimationFrame *animvalue = (SHalflifeAnimationFrame *)((u8*)anim + anim->offset[j]); | 1446 | SHalflifeAnimationFrame *animvalue = (SHalflifeAnimationFrame *)((u8*)anim + anim->offset[j]); |
1447 | 1447 | ||
1448 | s32 k = frame; | 1448 | s32 k = frame; |
1449 | // find span of values that includes the frame we want | 1449 | // find span of values that includes the frame we want |
1450 | while (animvalue->num.total <= k) | 1450 | while (animvalue->num.total <= k) |
1451 | { | 1451 | { |
1452 | k -= animvalue->num.total; | 1452 | k -= animvalue->num.total; |
1453 | animvalue += animvalue->num.valid + 1; | 1453 | animvalue += animvalue->num.valid + 1; |
1454 | } | 1454 | } |
1455 | // if we're inside the span | 1455 | // if we're inside the span |
1456 | if (animvalue->num.valid > k) | 1456 | if (animvalue->num.valid > k) |
1457 | { | 1457 | { |
1458 | // and there's more data in the span | 1458 | // and there's more data in the span |
1459 | if (animvalue->num.valid > k + 1) | 1459 | if (animvalue->num.valid > k + 1) |
1460 | { | 1460 | { |
1461 | pos[j] += (animvalue[k+1].value * (1.f - s) + s * animvalue[k+2].value) * bone->scale[j]; | 1461 | pos[j] += (animvalue[k+1].value * (1.f - s) + s * animvalue[k+2].value) * bone->scale[j]; |
1462 | } | 1462 | } |
1463 | else | 1463 | else |
1464 | { | 1464 | { |
1465 | pos[j] += animvalue[k+1].value * bone->scale[j]; | 1465 | pos[j] += animvalue[k+1].value * bone->scale[j]; |
1466 | } | 1466 | } |
1467 | } | 1467 | } |
1468 | else | 1468 | else |
1469 | { | 1469 | { |
1470 | // are we at the end of the repeating values section and there's another section with data? | 1470 | // are we at the end of the repeating values section and there's another section with data? |
1471 | if (animvalue->num.total <= k + 1) | 1471 | if (animvalue->num.total <= k + 1) |
1472 | { | 1472 | { |
1473 | pos[j] += (animvalue[animvalue->num.valid].value * (1.f - s) + s * animvalue[animvalue->num.valid + 2].value) * bone->scale[j]; | 1473 | pos[j] += (animvalue[animvalue->num.valid].value * (1.f - s) + s * animvalue[animvalue->num.valid + 2].value) * bone->scale[j]; |
1474 | } | 1474 | } |
1475 | else | 1475 | else |
1476 | { | 1476 | { |
1477 | pos[j] += animvalue[animvalue->num.valid].value * bone->scale[j]; | 1477 | pos[j] += animvalue[animvalue->num.valid].value * bone->scale[j]; |
1478 | } | 1478 | } |
1479 | } | 1479 | } |
1480 | } | 1480 | } |
1481 | if (bone->bonecontroller[j] != -1) | 1481 | if (bone->bonecontroller[j] != -1) |
1482 | { | 1482 | { |
1483 | pos[j] += BoneAdj[bone->bonecontroller[j]]; | 1483 | pos[j] += BoneAdj[bone->bonecontroller[j]]; |
1484 | } | 1484 | } |
1485 | } | 1485 | } |
1486 | } | 1486 | } |
1487 | 1487 | ||
1488 | 1488 | ||
1489 | /*! | 1489 | /*! |
1490 | */ | 1490 | */ |
1491 | void CAnimatedMeshHalfLife::calcRotations(vec3_hl *pos, vec4_hl *q, | 1491 | void CAnimatedMeshHalfLife::calcRotations(vec3_hl *pos, vec4_hl *q, |
1492 | SHalflifeSequence *seq, SHalflifeAnimOffset *anim, f32 f) | 1492 | SHalflifeSequence *seq, SHalflifeAnimOffset *anim, f32 f) |
1493 | { | 1493 | { |
1494 | s32 frame = (s32)f; | 1494 | s32 frame = (s32)f; |
1495 | f32 s = (f - frame); | 1495 | f32 s = (f - frame); |
1496 | 1496 | ||
1497 | // add in programatic controllers | 1497 | // add in programatic controllers |
1498 | calcBoneAdj(); | 1498 | calcBoneAdj(); |
1499 | 1499 | ||
1500 | SHalflifeBone *bone = (SHalflifeBone *)((u8 *)Header + Header->boneindex); | 1500 | SHalflifeBone *bone = (SHalflifeBone *)((u8 *)Header + Header->boneindex); |
1501 | for ( u32 i = 0; i < Header->numbones; i++, bone++, anim++) | 1501 | for ( u32 i = 0; i < Header->numbones; i++, bone++, anim++) |
1502 | { | 1502 | { |
1503 | core::vector3df angle1, angle2; | 1503 | core::vector3df angle1, angle2; |
1504 | calcBoneQuaternion(frame, bone, anim, 0, angle1.X, angle2.X); | 1504 | calcBoneQuaternion(frame, bone, anim, 0, angle1.X, angle2.X); |
1505 | calcBoneQuaternion(frame, bone, anim, 1, angle1.Y, angle2.Y); | 1505 | calcBoneQuaternion(frame, bone, anim, 1, angle1.Y, angle2.Y); |
1506 | calcBoneQuaternion(frame, bone, anim, 2, angle1.Z, angle2.Z); | 1506 | calcBoneQuaternion(frame, bone, anim, 2, angle1.Z, angle2.Z); |
1507 | 1507 | ||
1508 | if (!angle1.equals(angle2)) | 1508 | if (!angle1.equals(angle2)) |
1509 | { | 1509 | { |
1510 | vec4_hl q1, q2; | 1510 | vec4_hl q1, q2; |
1511 | AngleQuaternion( angle1, q1 ); | 1511 | AngleQuaternion( angle1, q1 ); |
1512 | AngleQuaternion( angle2, q2 ); | 1512 | AngleQuaternion( angle2, q2 ); |
1513 | QuaternionSlerp( q1, q2, s, q[i] ); | 1513 | QuaternionSlerp( q1, q2, s, q[i] ); |
1514 | } | 1514 | } |
1515 | else | 1515 | else |
1516 | { | 1516 | { |
1517 | AngleQuaternion( angle1, q[i] ); | 1517 | AngleQuaternion( angle1, q[i] ); |
1518 | } | 1518 | } |
1519 | 1519 | ||
1520 | calcBonePosition(frame, s, bone, anim, pos[i]); | 1520 | calcBonePosition(frame, s, bone, anim, pos[i]); |
1521 | } | 1521 | } |
1522 | 1522 | ||
1523 | if (seq->motiontype & STUDIO_X) | 1523 | if (seq->motiontype & STUDIO_X) |
1524 | pos[seq->motionbone][0] = 0.f; | 1524 | pos[seq->motionbone][0] = 0.f; |
1525 | if (seq->motiontype & STUDIO_Y) | 1525 | if (seq->motiontype & STUDIO_Y) |
1526 | pos[seq->motionbone][1] = 0.f; | 1526 | pos[seq->motionbone][1] = 0.f; |
1527 | if (seq->motiontype & STUDIO_Z) | 1527 | if (seq->motiontype & STUDIO_Z) |
1528 | pos[seq->motionbone][2] = 0.f; | 1528 | pos[seq->motionbone][2] = 0.f; |
1529 | } | 1529 | } |
1530 | 1530 | ||
1531 | 1531 | ||
1532 | /*! | 1532 | /*! |
1533 | */ | 1533 | */ |
1534 | SHalflifeAnimOffset * CAnimatedMeshHalfLife::getAnim( SHalflifeSequence *seq ) | 1534 | SHalflifeAnimOffset * CAnimatedMeshHalfLife::getAnim( SHalflifeSequence *seq ) |
1535 | { | 1535 | { |
1536 | SHalflifeSequenceGroup *seqgroup = (SHalflifeSequenceGroup *)((u8*)Header + Header->seqgroupindex) + seq->seqgroup; | 1536 | SHalflifeSequenceGroup *seqgroup = (SHalflifeSequenceGroup *)((u8*)Header + Header->seqgroupindex) + seq->seqgroup; |
1537 | 1537 | ||
1538 | if (seq->seqgroup == 0) | 1538 | if (seq->seqgroup == 0) |
1539 | { | 1539 | { |
1540 | return (SHalflifeAnimOffset *)((u8*)Header + seqgroup->data + seq->animindex); | 1540 | return (SHalflifeAnimOffset *)((u8*)Header + seqgroup->data + seq->animindex); |
1541 | } | 1541 | } |
1542 | 1542 | ||
1543 | return (SHalflifeAnimOffset *)((u8*)AnimationHeader[seq->seqgroup] + seq->animindex); | 1543 | return (SHalflifeAnimOffset *)((u8*)AnimationHeader[seq->seqgroup] + seq->animindex); |
1544 | } | 1544 | } |
1545 | 1545 | ||
1546 | 1546 | ||
1547 | /*! | 1547 | /*! |
1548 | */ | 1548 | */ |
1549 | void CAnimatedMeshHalfLife::slerpBones(vec4_hl q1[], vec3_hl pos1[], vec4_hl q2[], vec3_hl pos2[], f32 s) | 1549 | void CAnimatedMeshHalfLife::slerpBones(vec4_hl q1[], vec3_hl pos1[], vec4_hl q2[], vec3_hl pos2[], f32 s) |
1550 | { | 1550 | { |
1551 | if (s < 0) | 1551 | if (s < 0) |
1552 | s = 0; | 1552 | s = 0; |
1553 | else if (s > 1.f) | 1553 | else if (s > 1.f) |
1554 | s = 1.f; | 1554 | s = 1.f; |
1555 | 1555 | ||
1556 | f32 s1 = 1.f - s; | 1556 | f32 s1 = 1.f - s; |
1557 | 1557 | ||
1558 | for ( u32 i = 0; i < Header->numbones; i++) | 1558 | for ( u32 i = 0; i < Header->numbones; i++) |
1559 | { | 1559 | { |
1560 | vec4_hl q3; | 1560 | vec4_hl q3; |
1561 | QuaternionSlerp( q1[i], q2[i], s, q3 ); | 1561 | QuaternionSlerp( q1[i], q2[i], s, q3 ); |
1562 | q1[i][0] = q3[0]; | 1562 | q1[i][0] = q3[0]; |
1563 | q1[i][1] = q3[1]; | 1563 | q1[i][1] = q3[1]; |
1564 | q1[i][2] = q3[2]; | 1564 | q1[i][2] = q3[2]; |
1565 | q1[i][3] = q3[3]; | 1565 | q1[i][3] = q3[3]; |
1566 | pos1[i][0] = pos1[i][0] * s1 + pos2[i][0] * s; | 1566 | pos1[i][0] = pos1[i][0] * s1 + pos2[i][0] * s; |
1567 | pos1[i][1] = pos1[i][1] * s1 + pos2[i][1] * s; | 1567 | pos1[i][1] = pos1[i][1] * s1 + pos2[i][1] * s; |
1568 | pos1[i][2] = pos1[i][2] * s1 + pos2[i][2] * s; | 1568 | pos1[i][2] = pos1[i][2] * s1 + pos2[i][2] * s; |
1569 | } | 1569 | } |
1570 | } | 1570 | } |
1571 | 1571 | ||
1572 | 1572 | ||
1573 | /*! | 1573 | /*! |
1574 | */ | 1574 | */ |
1575 | void CAnimatedMeshHalfLife::setUpBones() | 1575 | void CAnimatedMeshHalfLife::setUpBones() |
1576 | { | 1576 | { |
1577 | static vec3_hl pos[MAXSTUDIOBONES]; | 1577 | static vec3_hl pos[MAXSTUDIOBONES]; |
1578 | f32 bonematrix[3][4]; | 1578 | f32 bonematrix[3][4]; |
1579 | static vec4_hl q[MAXSTUDIOBONES]; | 1579 | static vec4_hl q[MAXSTUDIOBONES]; |
1580 | 1580 | ||
1581 | static vec3_hl pos2[MAXSTUDIOBONES]; | 1581 | static vec3_hl pos2[MAXSTUDIOBONES]; |
1582 | static vec4_hl q2[MAXSTUDIOBONES]; | 1582 | static vec4_hl q2[MAXSTUDIOBONES]; |
1583 | static vec3_hl pos3[MAXSTUDIOBONES]; | 1583 | static vec3_hl pos3[MAXSTUDIOBONES]; |
1584 | static vec4_hl q3[MAXSTUDIOBONES]; | 1584 | static vec4_hl q3[MAXSTUDIOBONES]; |
1585 | static vec3_hl pos4[MAXSTUDIOBONES]; | 1585 | static vec3_hl pos4[MAXSTUDIOBONES]; |
1586 | static vec4_hl q4[MAXSTUDIOBONES]; | 1586 | static vec4_hl q4[MAXSTUDIOBONES]; |
1587 | 1587 | ||
1588 | if (SequenceIndex >= Header->numseq) | 1588 | if (SequenceIndex >= Header->numseq) |
1589 | SequenceIndex = 0; | 1589 | SequenceIndex = 0; |
1590 | 1590 | ||
1591 | SHalflifeSequence *seq = (SHalflifeSequence *)((u8*) Header + Header->seqindex) + SequenceIndex; | 1591 | SHalflifeSequence *seq = (SHalflifeSequence *)((u8*) Header + Header->seqindex) + SequenceIndex; |
1592 | 1592 | ||
1593 | SHalflifeAnimOffset *anim = getAnim(seq); | 1593 | SHalflifeAnimOffset *anim = getAnim(seq); |
1594 | calcRotations(pos, q, seq, anim, CurrentFrame); | 1594 | calcRotations(pos, q, seq, anim, CurrentFrame); |
1595 | 1595 | ||
1596 | if (seq->numblends > 1) | 1596 | if (seq->numblends > 1) |
1597 | { | 1597 | { |
1598 | anim += Header->numbones; | 1598 | anim += Header->numbones; |
1599 | calcRotations( pos2, q2, seq, anim, CurrentFrame ); | 1599 | calcRotations( pos2, q2, seq, anim, CurrentFrame ); |
1600 | f32 s = Blending[0] / 255.f; | 1600 | f32 s = Blending[0] / 255.f; |
1601 | 1601 | ||
1602 | slerpBones( q, pos, q2, pos2, s ); | 1602 | slerpBones( q, pos, q2, pos2, s ); |
1603 | 1603 | ||
1604 | if (seq->numblends == 4) | 1604 | if (seq->numblends == 4) |
1605 | { | 1605 | { |
1606 | anim += Header->numbones; | 1606 | anim += Header->numbones; |
1607 | calcRotations( pos3, q3, seq, anim, CurrentFrame ); | 1607 | calcRotations( pos3, q3, seq, anim, CurrentFrame ); |
1608 | 1608 | ||
1609 | anim += Header->numbones; | 1609 | anim += Header->numbones; |
1610 | calcRotations( pos4, q4, seq, anim, CurrentFrame ); | 1610 | calcRotations( pos4, q4, seq, anim, CurrentFrame ); |
1611 | 1611 | ||
1612 | s = Blending[0] / 255.f; | 1612 | s = Blending[0] / 255.f; |
1613 | slerpBones( q3, pos3, q4, pos4, s ); | 1613 | slerpBones( q3, pos3, q4, pos4, s ); |
1614 | 1614 | ||
1615 | s = Blending[1] / 255.f; | 1615 | s = Blending[1] / 255.f; |
1616 | slerpBones( q, pos, q3, pos3, s ); | 1616 | slerpBones( q, pos, q3, pos3, s ); |
1617 | } | 1617 | } |
1618 | } | 1618 | } |
1619 | 1619 | ||
1620 | SHalflifeBone *bone = (SHalflifeBone *)((u8*) Header + Header->boneindex); | 1620 | SHalflifeBone *bone = (SHalflifeBone *)((u8*) Header + Header->boneindex); |
1621 | 1621 | ||
1622 | for (u32 i = 0; i < Header->numbones; i++) | 1622 | for (u32 i = 0; i < Header->numbones; i++) |
1623 | { | 1623 | { |
1624 | QuaternionMatrix( q[i], bonematrix ); | 1624 | QuaternionMatrix( q[i], bonematrix ); |
1625 | 1625 | ||
1626 | bonematrix[0][3] = pos[i][0]; | 1626 | bonematrix[0][3] = pos[i][0]; |
1627 | bonematrix[1][3] = pos[i][1]; | 1627 | bonematrix[1][3] = pos[i][1]; |
1628 | bonematrix[2][3] = pos[i][2]; | 1628 | bonematrix[2][3] = pos[i][2]; |
1629 | 1629 | ||
1630 | if (bone[i].parent == -1) { | 1630 | if (bone[i].parent == -1) { |
1631 | memcpy(BoneTransform[i], bonematrix, sizeof(f32) * 12); | 1631 | memcpy(BoneTransform[i], bonematrix, sizeof(f32) * 12); |
1632 | } | 1632 | } |
1633 | else { | 1633 | else { |
1634 | R_ConcatTransforms (BoneTransform[bone[i].parent], bonematrix, BoneTransform[i]); | 1634 | R_ConcatTransforms (BoneTransform[bone[i].parent], bonematrix, BoneTransform[i]); |
1635 | } | 1635 | } |
1636 | } | 1636 | } |
1637 | } | 1637 | } |
1638 | 1638 | ||
1639 | 1639 | ||
1640 | //! Returns an axis aligned bounding box | 1640 | //! Returns an axis aligned bounding box |
1641 | const core::aabbox3d<f32>& CAnimatedMeshHalfLife::getBoundingBox() const | 1641 | const core::aabbox3d<f32>& CAnimatedMeshHalfLife::getBoundingBox() const |
1642 | { | 1642 | { |
1643 | return MeshIPol->BoundingBox; | 1643 | return MeshIPol->BoundingBox; |
1644 | } | 1644 | } |
1645 | 1645 | ||
1646 | 1646 | ||
1647 | //! Returns the type of the animated mesh. | 1647 | //! Returns the type of the animated mesh. |
1648 | E_ANIMATED_MESH_TYPE CAnimatedMeshHalfLife::getMeshType() const | 1648 | E_ANIMATED_MESH_TYPE CAnimatedMeshHalfLife::getMeshType() const |
1649 | { | 1649 | { |
1650 | return EAMT_MDL_HALFLIFE; | 1650 | return EAMT_MDL_HALFLIFE; |
1651 | } | 1651 | } |
1652 | 1652 | ||
1653 | 1653 | ||
1654 | //! returns amount of mesh buffers. | 1654 | //! returns amount of mesh buffers. |
1655 | u32 CAnimatedMeshHalfLife::getMeshBufferCount() const | 1655 | u32 CAnimatedMeshHalfLife::getMeshBufferCount() const |
1656 | { | 1656 | { |
1657 | return MeshIPol->getMeshBufferCount(); | 1657 | return MeshIPol->getMeshBufferCount(); |
1658 | } | 1658 | } |
1659 | 1659 | ||
1660 | 1660 | ||
1661 | //! returns pointer to a mesh buffer | 1661 | //! returns pointer to a mesh buffer |
1662 | IMeshBuffer* CAnimatedMeshHalfLife::getMeshBuffer(u32 nr) const | 1662 | IMeshBuffer* CAnimatedMeshHalfLife::getMeshBuffer(u32 nr) const |
1663 | { | 1663 | { |
1664 | return MeshIPol->getMeshBuffer(nr); | 1664 | return MeshIPol->getMeshBuffer(nr); |
1665 | } | 1665 | } |
1666 | 1666 | ||
1667 | 1667 | ||
1668 | //! Returns pointer to a mesh buffer which fits a material | 1668 | //! Returns pointer to a mesh buffer which fits a material |
1669 | /** \param material: material to search for | 1669 | /** \param material: material to search for |
1670 | \return Returns the pointer to the mesh buffer or | 1670 | \return Returns the pointer to the mesh buffer or |
1671 | NULL if there is no such mesh buffer. */ | 1671 | NULL if there is no such mesh buffer. */ |
1672 | IMeshBuffer* CAnimatedMeshHalfLife::getMeshBuffer(const video::SMaterial &material) const | 1672 | IMeshBuffer* CAnimatedMeshHalfLife::getMeshBuffer(const video::SMaterial &material) const |
1673 | { | 1673 | { |
1674 | return MeshIPol->getMeshBuffer(material); | 1674 | return MeshIPol->getMeshBuffer(material); |
1675 | } | 1675 | } |
1676 | 1676 | ||
1677 | 1677 | ||
1678 | void CAnimatedMeshHalfLife::setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) | 1678 | void CAnimatedMeshHalfLife::setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) |
1679 | { | 1679 | { |
1680 | MeshIPol->setMaterialFlag ( flag, newvalue ); | 1680 | MeshIPol->setMaterialFlag ( flag, newvalue ); |
1681 | } | 1681 | } |
1682 | 1682 | ||
1683 | 1683 | ||
1684 | //! set user axis aligned bounding box | 1684 | //! set user axis aligned bounding box |
1685 | void CAnimatedMeshHalfLife::setBoundingBox(const core::aabbox3df& box) | 1685 | void CAnimatedMeshHalfLife::setBoundingBox(const core::aabbox3df& box) |
1686 | { | 1686 | { |
1687 | MeshIPol->setBoundingBox(box); | 1687 | MeshIPol->setBoundingBox(box); |
1688 | } | 1688 | } |
1689 | 1689 | ||
1690 | 1690 | ||
1691 | } // end namespace scene | 1691 | } // end namespace scene |
1692 | } // end namespace irr | 1692 | } // end namespace irr |
1693 | 1693 | ||
1694 | #endif // _IRR_COMPILE_WITH_MD3_LOADER_ | 1694 | #endif // _IRR_COMPILE_WITH_MD3_LOADER_ |
1695 | 1695 | ||