Surface_SweptSpline.cpp (6982B)
1 /* 2 =========================================================================== 3 4 Doom 3 BFG Edition GPL Source Code 5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 6 7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). 8 9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation, either version 3 of the License, or 12 (at your option) any later version. 13 14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>. 21 22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below. 23 24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. 25 26 =========================================================================== 27 */ 28 29 #pragma hdrstop 30 #include "../precompiled.h" 31 32 /* 33 ==================== 34 idSurface_SweptSpline::SetSpline 35 ==================== 36 */ 37 void idSurface_SweptSpline::SetSpline( idCurve_Spline<idVec4> *spline ) { 38 if ( this->spline ) { 39 delete this->spline; 40 } 41 this->spline = spline; 42 } 43 44 /* 45 ==================== 46 idSurface_SweptSpline::SetSweptSpline 47 ==================== 48 */ 49 void idSurface_SweptSpline::SetSweptSpline( idCurve_Spline<idVec4> *sweptSpline ) { 50 if ( this->sweptSpline ) { 51 delete this->sweptSpline; 52 } 53 this->sweptSpline = sweptSpline; 54 } 55 56 /* 57 ==================== 58 idSurface_SweptSpline::SetSweptCircle 59 60 Sets the swept spline to a NURBS circle. 61 ==================== 62 */ 63 void idSurface_SweptSpline::SetSweptCircle( const float radius ) { 64 idCurve_NURBS<idVec4> *nurbs = new (TAG_IDLIB_SURFACE) idCurve_NURBS<idVec4>(); 65 nurbs->Clear(); 66 nurbs->AddValue( 0.0f, idVec4( radius, radius, 0.0f, 0.00f ) ); 67 nurbs->AddValue( 100.0f, idVec4( -radius, radius, 0.0f, 0.25f ) ); 68 nurbs->AddValue( 200.0f, idVec4( -radius, -radius, 0.0f, 0.50f ) ); 69 nurbs->AddValue( 300.0f, idVec4( radius, -radius, 0.0f, 0.75f ) ); 70 nurbs->SetBoundaryType( idCurve_NURBS<idVec4>::BT_CLOSED ); 71 nurbs->SetCloseTime( 100.0f ); 72 if ( sweptSpline ) { 73 delete sweptSpline; 74 } 75 sweptSpline = nurbs; 76 } 77 78 /* 79 ==================== 80 idSurface_SweptSpline::GetFrame 81 ==================== 82 */ 83 void idSurface_SweptSpline::GetFrame( const idMat3 &previousFrame, const idVec3 dir, idMat3 &newFrame ) { 84 float wx, wy, wz; 85 float xx, yy, yz; 86 float xy, xz, zz; 87 float x2, y2, z2; 88 float a, c, s, x, y, z; 89 idVec3 d, v; 90 idMat3 axis; 91 92 d = dir; 93 d.Normalize(); 94 v = d.Cross( previousFrame[2] ); 95 v.Normalize(); 96 97 a = idMath::ACos( previousFrame[2] * d ) * 0.5f; 98 c = idMath::Cos( a ); 99 s = idMath::Sqrt( 1.0f - c * c ); 100 101 x = v[0] * s; 102 y = v[1] * s; 103 z = v[2] * s; 104 105 x2 = x + x; 106 y2 = y + y; 107 z2 = z + z; 108 xx = x * x2; 109 xy = x * y2; 110 xz = x * z2; 111 yy = y * y2; 112 yz = y * z2; 113 zz = z * z2; 114 wx = c * x2; 115 wy = c * y2; 116 wz = c * z2; 117 118 axis[0][0] = 1.0f - ( yy + zz ); 119 axis[0][1] = xy - wz; 120 axis[0][2] = xz + wy; 121 axis[1][0] = xy + wz; 122 axis[1][1] = 1.0f - ( xx + zz ); 123 axis[1][2] = yz - wx; 124 axis[2][0] = xz - wy; 125 axis[2][1] = yz + wx; 126 axis[2][2] = 1.0f - ( xx + yy ); 127 128 newFrame = previousFrame * axis; 129 130 newFrame[2] = dir; 131 newFrame[2].Normalize(); 132 newFrame[1].Cross( newFrame[ 2 ], newFrame[ 0 ] ); 133 newFrame[1].Normalize(); 134 newFrame[0].Cross( newFrame[ 1 ], newFrame[ 2 ] ); 135 newFrame[0].Normalize(); 136 } 137 138 /* 139 ==================== 140 idSurface_SweptSpline::Tessellate 141 142 tesselate the surface 143 ==================== 144 */ 145 void idSurface_SweptSpline::Tessellate( const int splineSubdivisions, const int sweptSplineSubdivisions ) { 146 int i, j, offset, baseOffset, splineDiv, sweptSplineDiv; 147 int i0, i1, j0, j1; 148 float totalTime, t; 149 idVec4 splinePos, splineD1; 150 idMat3 splineMat; 151 152 if ( !spline || !sweptSpline ) { 153 idSurface::Clear(); 154 return; 155 } 156 157 verts.SetNum( splineSubdivisions * sweptSplineSubdivisions ); 158 159 // calculate the points and first derivatives for the swept spline 160 totalTime = sweptSpline->GetTime( sweptSpline->GetNumValues() - 1 ) - sweptSpline->GetTime( 0 ) + sweptSpline->GetCloseTime(); 161 sweptSplineDiv = sweptSpline->GetBoundaryType() == idCurve_Spline<idVec3>::BT_CLOSED ? sweptSplineSubdivisions : sweptSplineSubdivisions - 1; 162 baseOffset = (splineSubdivisions-1) * sweptSplineSubdivisions; 163 for ( i = 0; i < sweptSplineSubdivisions; i++ ) { 164 t = totalTime * i / sweptSplineDiv; 165 splinePos = sweptSpline->GetCurrentValue( t ); 166 splineD1 = sweptSpline->GetCurrentFirstDerivative( t ); 167 verts[baseOffset+i].xyz = splinePos.ToVec3(); 168 verts[baseOffset+i].SetTexCoordS( splinePos.w ); 169 verts[baseOffset+i].SetTangent( splineD1.ToVec3() ); 170 } 171 172 // sweep the spline 173 totalTime = spline->GetTime( spline->GetNumValues() - 1 ) - spline->GetTime( 0 ) + spline->GetCloseTime(); 174 splineDiv = spline->GetBoundaryType() == idCurve_Spline<idVec3>::BT_CLOSED ? splineSubdivisions : splineSubdivisions - 1; 175 splineMat.Identity(); 176 idVec3 tempNormal; 177 for ( i = 0; i < splineSubdivisions; i++ ) { 178 t = totalTime * i / splineDiv; 179 180 splinePos = spline->GetCurrentValue( t ); 181 splineD1 = spline->GetCurrentFirstDerivative( t ); 182 183 GetFrame( splineMat, splineD1.ToVec3(), splineMat ); 184 185 offset = i * sweptSplineSubdivisions; 186 for ( j = 0; j < sweptSplineSubdivisions; j++ ) { 187 idDrawVert *v = &verts[offset+j]; 188 v->xyz = splinePos.ToVec3() + verts[baseOffset+j].xyz * splineMat; 189 v->SetTexCoord( verts[baseOffset+j].GetTexCoord().x, splinePos.w ); 190 v->SetTangent( verts[baseOffset+j].GetTangent() * splineMat ); 191 v->SetBiTangent( splineD1.ToVec3() ); 192 tempNormal = v->GetBiTangent().Cross( v->GetTangent() ); 193 tempNormal.Normalize(); 194 v->SetNormal( tempNormal ); 195 v->color[0] = v->color[1] = v->color[2] = v->color[3] = 0; 196 } 197 } 198 199 indexes.SetNum( splineDiv * sweptSplineDiv * 2 * 3 ); 200 201 // create indexes for the triangles 202 for ( offset = i = 0; i < splineDiv; i++ ) { 203 204 i0 = (i+0) * sweptSplineSubdivisions; 205 i1 = (i+1) % splineSubdivisions * sweptSplineSubdivisions; 206 207 for ( j = 0; j < sweptSplineDiv; j++ ) { 208 209 j0 = (j+0); 210 j1 = (j+1) % sweptSplineSubdivisions; 211 212 indexes[offset++] = i0 + j0; 213 indexes[offset++] = i0 + j1; 214 indexes[offset++] = i1 + j1; 215 216 indexes[offset++] = i1 + j1; 217 indexes[offset++] = i1 + j0; 218 indexes[offset++] = i0 + j0; 219 } 220 } 221 222 GenerateEdgeIndexes(); 223 }