DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

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 }