aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llhudeffectbeam.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llhudeffectbeam.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/llhudeffectbeam.cpp')
-rw-r--r--linden/indra/newview/llhudeffectbeam.cpp390
1 files changed, 390 insertions, 0 deletions
diff --git a/linden/indra/newview/llhudeffectbeam.cpp b/linden/indra/newview/llhudeffectbeam.cpp
new file mode 100644
index 0000000..a7e7a5e
--- /dev/null
+++ b/linden/indra/newview/llhudeffectbeam.cpp
@@ -0,0 +1,390 @@
1/**
2 * @file llhudeffectbeam.cpp
3 * @brief LLHUDEffectBeam class implementation
4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "llviewerprecompiledheaders.h"
29
30#include "llhudeffectbeam.h"
31#include "message.h"
32
33#include "llviewerobjectlist.h"
34
35#include "llagent.h"
36#include "lldrawable.h"
37#include "llfontgl.h"
38#include "llgl.h"
39#include "llglheaders.h"
40#include "llhudrender.h"
41#include "llimagegl.h"
42#include "llsphere.h"
43#include "llviewercamera.h"
44#include "llvoavatar.h"
45#include "llviewercontrol.h"
46
47const F32 BEAM_SPACING = 0.075f;
48
49LLHUDEffectBeam::LLHUDEffectBeam(const U8 type) : LLHUDEffect(type)
50{
51 mKillTime = mDuration;
52
53 // Initialize all of these to defaults
54 S32 i;
55 for (i = 0; i < NUM_POINTS; i++)
56 {
57 mInterp[i].setStartTime(BEAM_SPACING*i);
58 mInterp[i].setEndTime(BEAM_SPACING*NUM_POINTS + BEAM_SPACING*i);
59 mInterp[i].start();
60 mInterpFade[i].setStartTime(BEAM_SPACING*NUM_POINTS + BEAM_SPACING*i - 0.5f*NUM_POINTS*BEAM_SPACING);
61 mInterpFade[i].setEndTime(BEAM_SPACING*NUM_POINTS + BEAM_SPACING*i);
62 mInterpFade[i].setStartVal(1.f);
63 mInterpFade[i].setEndVal(0.f);
64 }
65
66 // Setup default timeouts and fade animations.
67 F32 fade_length;
68 fade_length = llmin(0.5f, mDuration);
69 mFadeInterp.setStartTime(mKillTime - fade_length);
70 mFadeInterp.setEndTime(mKillTime);
71 mFadeInterp.setStartVal(1.f);
72 mFadeInterp.setEndVal(0.f);
73}
74
75LLHUDEffectBeam::~LLHUDEffectBeam()
76{
77}
78
79void LLHUDEffectBeam::packData(LLMessageSystem *mesgsys)
80{
81 if (!mSourceObject)
82 {
83 llwarns << "Missing source object!" << llendl;
84 }
85
86 // Pack the default data
87 LLHUDEffect::packData(mesgsys);
88
89 // Pack the type-specific data. Uses a fun packed binary format. Whee!
90 // 16 + 24 + 1 = 41
91 U8 packed_data[41];
92 memset(packed_data, 0, 41);
93 if (mSourceObject)
94 {
95 htonmemcpy(packed_data, mSourceObject->mID.mData, MVT_LLUUID, 16);
96 }
97
98 if (mTargetObject)
99 {
100 packed_data[16] = 1;
101 }
102 else
103 {
104 packed_data[16] = 0;
105 }
106
107 if (mTargetObject)
108 {
109 htonmemcpy(&(packed_data[17]), mTargetObject->mID.mData, MVT_LLUUID, 16);
110 }
111 else
112 {
113 htonmemcpy(&(packed_data[17]), mTargetPos.mdV, MVT_LLVector3d, 24);
114 }
115 mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, 41);
116}
117
118void LLHUDEffectBeam::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
119{
120 llerrs << "Got beam!" << llendl;
121 BOOL use_target_object;
122 LLVector3d new_target;
123 U8 packed_data[41];
124
125 LLHUDEffect::unpackData(mesgsys, blocknum);
126 LLUUID source_id;
127 LLUUID target_id;
128 S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData);
129 if (size != 41)
130 {
131 llwarns << "Beam effect with bad size " << size << llendl;
132 return;
133 }
134 mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, 41, blocknum);
135
136 htonmemcpy(source_id.mData, packed_data, MVT_LLUUID, 16);
137
138 LLViewerObject *objp = gObjectList.findObject(source_id);
139 if (objp)
140 {
141 setSourceObject(objp);
142 }
143
144 use_target_object = packed_data[16];
145
146 if (use_target_object)
147 {
148 htonmemcpy(target_id.mData, &packed_data[17], MVT_LLUUID, 16);
149
150 LLViewerObject *objp = gObjectList.findObject(target_id);
151 if (objp)
152 {
153 setTargetObject(objp);
154 }
155 }
156 else
157 {
158 htonmemcpy(new_target.mdV, &(packed_data[17]), MVT_LLVector3d, 24);
159 setTargetPos(new_target);
160 }
161
162 // We've received an update for the effect, update the various timeouts
163 // and fade animations.
164 mKillTime = mTimer.getElapsedTimeF32() + mDuration;
165 F32 fade_length;
166 fade_length = llmin(0.5f, mDuration);
167 mFadeInterp.setStartTime(mKillTime - fade_length);
168 mFadeInterp.setEndTime(mKillTime);
169 mFadeInterp.setStartVal(1.f);
170 mFadeInterp.setEndVal(0.f);
171}
172
173void LLHUDEffectBeam::setSourceObject(LLViewerObject *objp)
174{
175 if (objp->isDead())
176 {
177 llwarns << "HUDEffectBeam: Source object is dead!" << llendl;
178 mSourceObject = NULL;
179 return;
180 }
181
182 if (mSourceObject == objp)
183 {
184 return;
185 }
186
187 mSourceObject = objp;
188 if (mSourceObject)
189 {
190 S32 i;
191 for (i = 0; i < NUM_POINTS; i++)
192 {
193 if (mSourceObject->isAvatar())
194 {
195 LLViewerObject *objp = mSourceObject;
196 LLVOAvatar *avatarp = (LLVOAvatar *)objp;
197 LLVector3d hand_pos_global = gAgent.getPosGlobalFromAgent(avatarp->mWristLeftp->getWorldPosition());
198 mInterp[i].setStartVal(hand_pos_global);
199 mInterp[i].start();
200 }
201 else
202 {
203 mInterp[i].setStartVal(mSourceObject->getPositionGlobal());
204 mInterp[i].start();
205 }
206 }
207 }
208}
209
210
211void LLHUDEffectBeam::setTargetObject(LLViewerObject *objp)
212{
213 if (mTargetObject->isDead())
214 {
215 llwarns << "HUDEffectBeam: Target object is dead!" << llendl;
216 }
217
218 mTargetObject = objp;
219}
220
221void LLHUDEffectBeam::setTargetPos(const LLVector3d &pos_global)
222{
223 mTargetPos = pos_global;
224 mTargetObject = NULL;
225}
226
227void LLHUDEffectBeam::render()
228{
229 if (!mSourceObject)
230 {
231 markDead();
232 return;
233 }
234 if (mSourceObject->isDead())
235 {
236 markDead();
237 return;
238 }
239
240 F32 time = mTimer.getElapsedTimeF32();
241
242 // Kill us if our time is over...
243 if (mKillTime < time)
244 {
245 markDead();
246 return;
247 }
248
249 LLGLSPipelineAlpha gls_pipeline_alpha;
250 LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
251
252
253 // Interpolate the global fade alpha
254 mFadeInterp.update(time);
255
256 if (mTargetObject.notNull() && mTargetObject->mDrawable.notNull())
257 {
258 // use viewer object position on freshly created objects
259 if (mTargetObject->mDrawable->getGeneration() == -1)
260 {
261 mTargetPos = mTargetObject->getPositionGlobal();
262 }
263 // otherwise use drawable
264 else
265 {
266 mTargetPos = gAgent.getPosGlobalFromAgent(mTargetObject->mDrawable->getPositionAgent());
267 }
268 }
269
270
271 // Init the color of the particles
272 LLColor4U coloru = mColor;
273
274 /*
275 // This is disabled for now - DJS
276
277 // Fade the alpha
278 coloru.mV[3] = mFadeInterp.getCurVal()*mColor.mV[3];
279
280 // Draw a regular "beam" that connects the source and target
281
282 // First, figure out start and end positions relative to the camera
283 LLVector3 start_pos_agent;
284 if (mSourceObject->getPCode() == LL_PCODE_LEGACY_AVATAR)
285 {
286 LLViewerObject *objp = mSourceObject;
287 LLVOAvatar *avatarp = (LLVOAvatar *)objp;
288 LLVector3d hand_pos_global = gAgent.getPosGlobalFromAgent(avatarp->mWristLeftp->getWorldPosition());
289 start_pos_agent = gAgent.getPosAgentFromGlobal(hand_pos_global);
290 }
291 else
292 {
293 start_pos_agent = mSourceObject->getPositionAgent();
294 }
295 LLVector3 start_pos_camera = (start_pos_agent - gAgent.getCameraPositionAgent());
296 LLVector3 target_pos_agent = gAgent.getPosAgentFromGlobal(mTargetPos);
297 LLVector3 target_pos_camera = target_pos_agent - gAgent.getCameraPositionAgent();
298
299 // Generate the right "up" vector which is perpendicular to the beam, make it 1/10 meter wide, going to a point.
300 LLVector3 camera_up = gCamera->getUpAxis();
301 LLVector3 camera_at = gCamera->getAtAxis();
302 LLVector3 up = target_pos_camera % start_pos_camera;
303 up.normVec();
304 up *= 0.1f;
305
306 // Draw the triangle for the beam.
307 LLVector3 vertex;
308 glColor4ubv(coloru.mV);
309 glBegin(GL_TRIANGLE_STRIP);
310 vertex = start_pos_agent + up;
311 glVertex3fv(vertex.mV);
312 vertex = start_pos_agent - up;
313 glVertex3fv(vertex.mV);
314 vertex = target_pos_agent;
315 glVertex3fv(vertex.mV);
316 glEnd();
317 */
318
319 // Draw the particles
320 S32 i;
321 for (i = 0; i < NUM_POINTS; i++)
322 {
323 mInterp[i].update(time);
324 if (!mInterp[i].isActive())
325 {
326 continue;
327 }
328 mInterpFade[i].update(time);
329
330 if (mInterp[i].isDone())
331 {
332 // Reinitialize the particle when the particle has finished its animation.
333 setupParticle(i);
334 }
335
336 F32 frac = mInterp[i].getCurFrac();
337 F32 scale = 0.025f + fabs(0.05f*sin(2.f*F_PI*(frac - time)));
338 scale *= mInterpFade[i].getCurVal();
339
340 LLVector3 pos_agent = gAgent.getPosAgentFromGlobal(mInterp[i].getCurVal());
341
342 F32 alpha = mFadeInterp.getCurVal()*mColor.mV[3];
343 alpha *= mInterpFade[i].getCurVal();
344 coloru.mV[3] = (U8)alpha;
345 glColor4ubv(coloru.mV);
346
347 glPushMatrix();
348 glTranslatef(pos_agent.mV[0], pos_agent.mV[1], pos_agent.mV[2]);
349 glScalef(scale, scale, scale);
350 gSphere.render(0);
351 glPopMatrix();
352 }
353}
354
355void LLHUDEffectBeam::setupParticle(const S32 i)
356{
357 LLVector3d start_pos_global;
358 if (mSourceObject->getPCode() == LL_PCODE_LEGACY_AVATAR)
359 {
360 LLViewerObject *objp = mSourceObject;
361 LLVOAvatar *avatarp = (LLVOAvatar *)objp;
362 start_pos_global = gAgent.getPosGlobalFromAgent(avatarp->mWristLeftp->getWorldPosition());
363 }
364 else
365 {
366 start_pos_global = mSourceObject->getPositionGlobal();
367 }
368
369 // Generate a random offset for the target point.
370 const F32 SCALE = 0.5f;
371 F32 x, y, z;
372 x = frand(SCALE) - 0.5f*SCALE;
373 y = frand(SCALE) - 0.5f*SCALE;
374 z = frand(SCALE) - 0.5f*SCALE;
375
376 LLVector3d target_pos_global(mTargetPos);
377 target_pos_global += LLVector3d(x, y, z);
378
379 mInterp[i].setStartTime(mInterp[i].getEndTime());
380 mInterp[i].setEndTime(mInterp[i].getStartTime() + BEAM_SPACING*NUM_POINTS);
381 mInterp[i].setStartVal(start_pos_global);
382 mInterp[i].setEndVal(target_pos_global);
383 mInterp[i].start();
384
385
386 // Setup the interpolator that fades out the alpha.
387 mInterpFade[i].setStartTime(mInterp[i].getStartTime() + BEAM_SPACING*NUM_POINTS - 0.5f*NUM_POINTS*BEAM_SPACING);
388 mInterpFade[i].setEndTime(mInterp[i].getStartTime() + BEAM_SPACING*NUM_POINTS - 0.05f);
389 mInterpFade[i].start();
390}