diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llvopartgroup.cpp | |
parent | README.txt (diff) | |
download | meta-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/llvopartgroup.cpp')
-rw-r--r-- | linden/indra/newview/llvopartgroup.cpp | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/linden/indra/newview/llvopartgroup.cpp b/linden/indra/newview/llvopartgroup.cpp new file mode 100644 index 0000000..10a765d --- /dev/null +++ b/linden/indra/newview/llvopartgroup.cpp | |||
@@ -0,0 +1,285 @@ | |||
1 | /** | ||
2 | * @file llvopartgroup.cpp | ||
3 | * @brief Group of particle systems | ||
4 | * | ||
5 | * Copyright (c) 2001-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 "llvopartgroup.h" | ||
31 | |||
32 | #include "llfasttimer.h" | ||
33 | #include "message.h" | ||
34 | #include "v2math.h" | ||
35 | |||
36 | #include "llagent.h" | ||
37 | #include "lldrawable.h" | ||
38 | #include "llface.h" | ||
39 | #include "llsky.h" | ||
40 | #include "llviewercamera.h" | ||
41 | #include "llviewerpartsim.h" | ||
42 | #include "llviewerregion.h" | ||
43 | #include "pipeline.h" | ||
44 | |||
45 | const F32 MAX_PART_LIFETIME = 120.f; | ||
46 | |||
47 | extern U64 gFrameTime; | ||
48 | |||
49 | LLVOPartGroup::LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) | ||
50 | : LLViewerObject(id, pcode, regionp), | ||
51 | mViewerPartGroupp(NULL) | ||
52 | { | ||
53 | setNumTEs(1); | ||
54 | setTETexture(0, LLUUID::null); | ||
55 | mbCanSelect = FALSE; // users can't select particle systems | ||
56 | mDebugColor = LLColor4(frand(1.f), frand(1.f), frand(1.f), 1.f); | ||
57 | } | ||
58 | |||
59 | |||
60 | LLVOPartGroup::~LLVOPartGroup() | ||
61 | { | ||
62 | } | ||
63 | |||
64 | BOOL LLVOPartGroup::isActive() const | ||
65 | { | ||
66 | return TRUE; | ||
67 | } | ||
68 | |||
69 | BOOL LLVOPartGroup::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) | ||
70 | { | ||
71 | if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES)) | ||
72 | { | ||
73 | gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); | ||
74 | } | ||
75 | |||
76 | // Particle groups don't need any of default idleUpdate velocity interpolation stuff. | ||
77 | //LLViewerObject::idleUpdate(agent, world, time); | ||
78 | return TRUE; | ||
79 | } | ||
80 | |||
81 | |||
82 | void LLVOPartGroup::setPixelAreaAndAngle(LLAgent &agent) | ||
83 | { | ||
84 | // mPixelArea is calculated during render | ||
85 | |||
86 | LLVector3 viewer_pos_agent = agent.getCameraPositionAgent(); | ||
87 | LLVector3 pos_agent = getRenderPosition(); | ||
88 | |||
89 | F32 dx = viewer_pos_agent.mV[VX] - pos_agent.mV[VX]; | ||
90 | F32 dy = viewer_pos_agent.mV[VY] - pos_agent.mV[VY]; | ||
91 | F32 dz = viewer_pos_agent.mV[VZ] - pos_agent.mV[VZ]; | ||
92 | |||
93 | F32 mid_scale = getMidScale(); | ||
94 | F32 range = sqrt(dx*dx + dy*dy + dz*dz); | ||
95 | |||
96 | if (range < 0.001f || isHUDAttachment()) // range == zero | ||
97 | { | ||
98 | mAppAngle = 180.f; | ||
99 | } | ||
100 | else | ||
101 | { | ||
102 | mAppAngle = (F32) atan2( mid_scale, range) * RAD_TO_DEG; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | void LLVOPartGroup::updateTextures(LLAgent &agent) | ||
107 | { | ||
108 | // Texture stats for particles will need to be updated in a different way... | ||
109 | } | ||
110 | |||
111 | |||
112 | LLDrawable* LLVOPartGroup::createDrawable(LLPipeline *pipeline) | ||
113 | { | ||
114 | pipeline->allocDrawable(this); | ||
115 | mDrawable->setLit(FALSE); | ||
116 | mDrawable->setRenderType(LLPipeline::RENDER_TYPE_PARTICLES); | ||
117 | |||
118 | LLDrawPool *pool = gPipeline.getPool(LLDrawPool::POOL_ALPHA); | ||
119 | mDrawable->setNumFaces(mViewerPartGroupp->getCount(), pool, getTEImage(0)); | ||
120 | return mDrawable; | ||
121 | } | ||
122 | |||
123 | const F32 MAX_PARTICLE_AREA_SCALE = 0.02f; // some tuned constant, limits on how much particle area to draw | ||
124 | |||
125 | BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) | ||
126 | { | ||
127 | LLFastTimer t(LLFastTimer::FTM_UPDATE_PARTICLES); | ||
128 | |||
129 | LLVector3 at; | ||
130 | LLVector3 up; | ||
131 | LLVector3 right; | ||
132 | LLVector3 position_agent; | ||
133 | LLVector3 camera_agent = gAgent.getCameraPositionAgent(); | ||
134 | LLVector2 uvs[4]; | ||
135 | |||
136 | uvs[0].setVec(0.f, 1.f); | ||
137 | uvs[1].setVec(0.f, 0.f); | ||
138 | uvs[2].setVec(1.f, 1.f); | ||
139 | uvs[3].setVec(1.f, 0.f); | ||
140 | |||
141 | LLDrawPool *drawpool = gPipeline.getPool(LLDrawPool::POOL_ALPHA); | ||
142 | S32 num_parts = mViewerPartGroupp->getCount(); | ||
143 | LLFace *facep; | ||
144 | |||
145 | if (!num_parts) | ||
146 | { | ||
147 | drawable->setNumFaces(0, drawpool, getTEImage(0)); | ||
148 | LLPipeline::sCompiles++; | ||
149 | return TRUE; | ||
150 | } | ||
151 | |||
152 | if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES))) | ||
153 | { | ||
154 | return TRUE; | ||
155 | } | ||
156 | |||
157 | // drawable->setNumFaces(num_parts, drawpool, getTEImage(0)); | ||
158 | drawable->setNumFacesFast(num_parts, drawpool, getTEImage(0)); | ||
159 | |||
160 | LLVector3 normal(-gCamera->getXAxis()); // make point agent face camera | ||
161 | |||
162 | LLStrider<LLVector3> verticesp; | ||
163 | LLStrider<LLVector3> normalsp; | ||
164 | LLStrider<LLVector2> texCoordsp; | ||
165 | U32 *indicesp = 0; | ||
166 | |||
167 | S32 vert_offset; | ||
168 | F32 tot_area = 0; | ||
169 | F32 max_area = LLViewerPartSim::getMaxPartCount() * MAX_PARTICLE_AREA_SCALE; | ||
170 | |||
171 | S32 count=0; | ||
172 | for (S32 i = 0; i < num_parts; i++) | ||
173 | { | ||
174 | const LLViewerPart &part = mViewerPartGroupp->mParticles[i]; | ||
175 | |||
176 | LLVector3 part_pos_agent(part.mPosAgent); | ||
177 | at = part_pos_agent - camera_agent; | ||
178 | |||
179 | //F32 invcamdist = 1.0f / at.magVec(); | ||
180 | //area += (part.mScale.mV[0]*invcamdist)*(part.mScale.mV[1]*invcamdist); | ||
181 | F32 camera_dist_squared = at.magVecSquared(); | ||
182 | F32 inv_camera_dist_squared; | ||
183 | if (camera_dist_squared > 1.f) | ||
184 | inv_camera_dist_squared = 1.f / camera_dist_squared; | ||
185 | else | ||
186 | inv_camera_dist_squared = 1.f; | ||
187 | F32 area = part.mScale.mV[0] * part.mScale.mV[1] * inv_camera_dist_squared; | ||
188 | tot_area += area; | ||
189 | if (tot_area > max_area) | ||
190 | { | ||
191 | break; | ||
192 | } | ||
193 | |||
194 | count++; | ||
195 | |||
196 | facep = drawable->getFace(i); | ||
197 | const F32 NEAR_PART_DIST_SQ = 5.f*5.f; // Only discard particles > 5 m from the camera | ||
198 | const F32 MIN_PART_AREA = .005f*.005f; // only less than 5 mm x 5 mm at 1 m from camera | ||
199 | if (camera_dist_squared > NEAR_PART_DIST_SQ && area < MIN_PART_AREA) | ||
200 | { | ||
201 | facep->setSize(0, 0); | ||
202 | continue; | ||
203 | } | ||
204 | facep->setSize(4, 6); | ||
205 | facep->mCenterAgent = part_pos_agent; | ||
206 | vert_offset = facep->getGeometry(verticesp,normalsp,texCoordsp, indicesp); | ||
207 | if (-1 == vert_offset) | ||
208 | { | ||
209 | return TRUE; | ||
210 | } | ||
211 | |||
212 | right = at % LLVector3(0.f, 0.f, 1.f); | ||
213 | right.normVec(); | ||
214 | up = right % at; | ||
215 | up.normVec(); | ||
216 | |||
217 | if (part.mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK) | ||
218 | { | ||
219 | LLVector3 normvel = part.mVelocity; | ||
220 | normvel.normVec(); | ||
221 | LLVector2 up_fracs; | ||
222 | up_fracs.mV[0] = normvel*right; | ||
223 | up_fracs.mV[1] = normvel*up; | ||
224 | up_fracs.normVec(); | ||
225 | |||
226 | LLVector3 new_up; | ||
227 | LLVector3 new_right; | ||
228 | new_up = up_fracs.mV[0] * right + up_fracs.mV[1]*up; | ||
229 | new_right = up_fracs.mV[1] * right - up_fracs.mV[0]*up; | ||
230 | up = new_up; | ||
231 | right = new_right; | ||
232 | up.normVec(); | ||
233 | right.normVec(); | ||
234 | } | ||
235 | |||
236 | right *= 0.5f*part.mScale.mV[0]; | ||
237 | up *= 0.5f*part.mScale.mV[1]; | ||
238 | |||
239 | *verticesp++ = part_pos_agent + up - right; | ||
240 | *verticesp++ = part_pos_agent - up - right; | ||
241 | *verticesp++ = part_pos_agent + up + right; | ||
242 | *verticesp++ = part_pos_agent - up + right; | ||
243 | |||
244 | *texCoordsp++ = uvs[0]; | ||
245 | *texCoordsp++ = uvs[1]; | ||
246 | *texCoordsp++ = uvs[2]; | ||
247 | *texCoordsp++ = uvs[3]; | ||
248 | |||
249 | *normalsp++ = normal; | ||
250 | *normalsp++ = normal; | ||
251 | *normalsp++ = normal; | ||
252 | *normalsp++ = normal; | ||
253 | |||
254 | if (part.mFlags & LLPartData::LL_PART_EMISSIVE_MASK) | ||
255 | { | ||
256 | facep->setState(LLFace::FULLBRIGHT); | ||
257 | } | ||
258 | else | ||
259 | { | ||
260 | facep->clearState(LLFace::FULLBRIGHT); | ||
261 | } | ||
262 | facep->setFaceColor(part.mColor); | ||
263 | |||
264 | *indicesp++ = vert_offset + 0; | ||
265 | *indicesp++ = vert_offset + 1; | ||
266 | *indicesp++ = vert_offset + 2; | ||
267 | |||
268 | *indicesp++ = vert_offset + 1; | ||
269 | *indicesp++ = vert_offset + 3; | ||
270 | *indicesp++ = vert_offset + 2; | ||
271 | } | ||
272 | for (S32 j = count; j < drawable->getNumFaces(); j++) | ||
273 | { | ||
274 | drawable->getFace(j)->setSize(0,0); | ||
275 | } | ||
276 | |||
277 | mPixelArea = tot_area * gCamera->getPixelMeterRatio() * gCamera->getPixelMeterRatio(); | ||
278 | const F32 area_scale = 10.f; // scale area to increase priority a bit | ||
279 | getTEImage(0)->addTextureStats(mPixelArea * area_scale); | ||
280 | |||
281 | LLPipeline::sCompiles++; | ||
282 | |||
283 | return TRUE; | ||
284 | } | ||
285 | |||