1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
8 
9 Doom 3 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 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 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 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 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 #include "sys/platform.h"
30 #include "renderer/tr_local.h"
31 
32 #include "renderer/Model_local.h"
33 
34 /*
35 
36 This is a simple dynamic model that just creates a stretched quad between
37 two points that faces the view, like a dynamic deform tube.
38 
39 */
40 
41 static const char *beam_SnapshotName = "_beam_Snapshot_";
42 
43 /*
44 ===============
45 idRenderModelBeam::IsDynamicModel
46 ===============
47 */
IsDynamicModel() const48 dynamicModel_t idRenderModelBeam::IsDynamicModel() const {
49 	return DM_CONTINUOUS;	// regenerate for every view
50 }
51 
52 /*
53 ===============
54 idRenderModelBeam::IsLoaded
55 ===============
56 */
IsLoaded() const57 bool idRenderModelBeam::IsLoaded() const {
58 	return true;	// don't ever need to load
59 }
60 
61 /*
62 ===============
63 idRenderModelBeam::InstantiateDynamicModel
64 ===============
65 */
InstantiateDynamicModel(const struct renderEntity_s * renderEntity,const struct viewDef_s * viewDef,idRenderModel * cachedModel)66 idRenderModel *idRenderModelBeam::InstantiateDynamicModel( const struct renderEntity_s *renderEntity, const struct viewDef_s *viewDef, idRenderModel *cachedModel ) {
67 	idRenderModelStatic *staticModel;
68 	srfTriangles_t *tri;
69 	modelSurface_t surf;
70 
71 	if ( cachedModel ) {
72 		delete cachedModel;
73 		cachedModel = NULL;
74 	}
75 
76 	if ( renderEntity == NULL || viewDef == NULL ) {
77 		delete cachedModel;
78 		return NULL;
79 	}
80 
81 	if ( cachedModel != NULL ) {
82 
83 		assert( dynamic_cast<idRenderModelStatic *>( cachedModel ) != NULL );
84 		assert( idStr::Icmp( cachedModel->Name(), beam_SnapshotName ) == 0 );
85 
86 		staticModel = static_cast<idRenderModelStatic *>( cachedModel );
87 		surf = *staticModel->Surface( 0 );
88 		tri = surf.geometry;
89 
90 	} else {
91 
92 		staticModel = new idRenderModelStatic;
93 		staticModel->InitEmpty( beam_SnapshotName );
94 
95 		tri = R_AllocStaticTriSurf();
96 		R_AllocStaticTriSurfVerts( tri, 4 );
97 		R_AllocStaticTriSurfIndexes( tri, 6 );
98 
99 		tri->verts[0].Clear();
100 		tri->verts[0].st[0] = 0;
101 		tri->verts[0].st[1] = 0;
102 
103 		tri->verts[1].Clear();
104 		tri->verts[1].st[0] = 0;
105 		tri->verts[1].st[1] = 1;
106 
107 		tri->verts[2].Clear();
108 		tri->verts[2].st[0] = 1;
109 		tri->verts[2].st[1] = 0;
110 
111 		tri->verts[3].Clear();
112 		tri->verts[3].st[0] = 1;
113 		tri->verts[3].st[1] = 1;
114 
115 		tri->indexes[0] = 0;
116 		tri->indexes[1] = 2;
117 		tri->indexes[2] = 1;
118 		tri->indexes[3] = 2;
119 		tri->indexes[4] = 3;
120 		tri->indexes[5] = 1;
121 
122 		tri->numVerts = 4;
123 		tri->numIndexes = 6;
124 
125 		surf.geometry = tri;
126 		surf.id = 0;
127 		surf.shader = tr.defaultMaterial;
128 		staticModel->AddSurface( surf );
129 	}
130 
131 	idVec3	target = *reinterpret_cast<const idVec3 *>( &renderEntity->shaderParms[SHADERPARM_BEAM_END_X] );
132 
133 	// we need the view direction to project the minor axis of the tube
134 	// as the view changes
135 	idVec3	localView, localTarget;
136 	float	modelMatrix[16];
137 	R_AxisToModelMatrix( renderEntity->axis, renderEntity->origin, modelMatrix );
138 	R_GlobalPointToLocal( modelMatrix, viewDef->renderView.vieworg, localView );
139 	R_GlobalPointToLocal( modelMatrix, target, localTarget );
140 
141 	idVec3	major = localTarget;
142 	idVec3	minor;
143 
144 	idVec3	mid = 0.5f * localTarget;
145 	idVec3	dir = mid - localView;
146 	minor.Cross( major, dir );
147 	minor.Normalize();
148 	if ( renderEntity->shaderParms[SHADERPARM_BEAM_WIDTH] != 0.0f ) {
149 		minor *= renderEntity->shaderParms[SHADERPARM_BEAM_WIDTH] * 0.5f;
150 	}
151 
152 	int red		= idMath::FtoiFast( renderEntity->shaderParms[SHADERPARM_RED] * 255.0f );
153 	int green	= idMath::FtoiFast( renderEntity->shaderParms[SHADERPARM_GREEN] * 255.0f );
154 	int blue	= idMath::FtoiFast( renderEntity->shaderParms[SHADERPARM_BLUE] * 255.0f );
155 	int alpha	= idMath::FtoiFast( renderEntity->shaderParms[SHADERPARM_ALPHA] * 255.0f );
156 
157 	tri->verts[0].xyz = minor;
158 	tri->verts[0].color[0] = red;
159 	tri->verts[0].color[1] = green;
160 	tri->verts[0].color[2] = blue;
161 	tri->verts[0].color[3] = alpha;
162 
163 	tri->verts[1].xyz = -minor;
164 	tri->verts[1].color[0] = red;
165 	tri->verts[1].color[1] = green;
166 	tri->verts[1].color[2] = blue;
167 	tri->verts[1].color[3] = alpha;
168 
169 	tri->verts[2].xyz = localTarget + minor;
170 	tri->verts[2].color[0] = red;
171 	tri->verts[2].color[1] = green;
172 	tri->verts[2].color[2] = blue;
173 	tri->verts[2].color[3] = alpha;
174 
175 	tri->verts[3].xyz = localTarget - minor;
176 	tri->verts[3].color[0] = red;
177 	tri->verts[3].color[1] = green;
178 	tri->verts[3].color[2] = blue;
179 	tri->verts[3].color[3] = alpha;
180 
181 	R_BoundTriSurf( tri );
182 
183 	staticModel->bounds = tri->bounds;
184 
185 	return staticModel;
186 }
187 
188 /*
189 ===============
190 idRenderModelBeam::Bounds
191 ===============
192 */
Bounds(const struct renderEntity_s * renderEntity) const193 idBounds idRenderModelBeam::Bounds( const struct renderEntity_s *renderEntity ) const {
194 	idBounds	b;
195 
196 	b.Zero();
197 	if ( !renderEntity ) {
198 		b.ExpandSelf( 8.0f );
199 	} else {
200 		idVec3	target = *reinterpret_cast<const idVec3 *>( &renderEntity->shaderParms[SHADERPARM_BEAM_END_X] );
201 		idVec3	localTarget;
202 		float	modelMatrix[16];
203 		R_AxisToModelMatrix( renderEntity->axis, renderEntity->origin, modelMatrix );
204 		R_GlobalPointToLocal( modelMatrix, target, localTarget );
205 
206 		b.AddPoint( localTarget );
207 		if ( renderEntity->shaderParms[SHADERPARM_BEAM_WIDTH] != 0.0f ) {
208 			b.ExpandSelf( renderEntity->shaderParms[SHADERPARM_BEAM_WIDTH] * 0.5f );
209 		}
210 	}
211 	return b;
212 }
213