Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
segline.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/***********************************************************************************************
20 *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
21 ***********************************************************************************************
22 * *
23 * Project Name : G *
24 * *
25 * $Archive:: /VSS_Sync/ww3d2/segline.cpp $*
26 * *
27 * $Author:: Vss_sync $*
28 * *
29 * $Modtime:: 8/29/01 7:29p $*
30 * *
31 * $Revision:: 23 $*
32 * *
33 *---------------------------------------------------------------------------------------------*
34 * Functions: *
35 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
36
37#include "segline.h"
38#include "ww3d.h"
39#include "rinfo.h"
40#include "predlod.h"
41#include "v3_rnd.h"
42#include "texture.h"
43#include "coltest.h"
44#include "w3d_file.h"
45#include "texture.h"
46#include "dx8wrapper.h"
47#include "vp.h"
48#include "vector3i.h"
49#include "sortingrenderer.h"
50
51static SegLineRendererClass _LineRenderer;
52
53
54/*
55** SegmentedLineClass implementation:
56*/
57
59 MaxSubdivisionLevels(0),
60 NormalizedScreenArea(0.0f)
61{
62}
63
65 MaxSubdivisionLevels(src.MaxSubdivisionLevels),
66 NormalizedScreenArea(src.NormalizedScreenArea),
67 PointLocations(src.PointLocations),
68 LineRenderer(src.LineRenderer)
69{
70}
71
73{
75
76 if (this != &that) {
77
78 MaxSubdivisionLevels = that.MaxSubdivisionLevels;
79 NormalizedScreenArea = that.NormalizedScreenArea;
80 PointLocations = that.PointLocations;
81 LineRenderer = that.LineRenderer;
82 }
83
84 return * this;
85}
86
90
92{
93 LineRenderer.Reset_Line();
94}
95
96
97// These are segment points, and include the start and end point of the
98// entire line. Therefore there must be at least two.
99void SegmentedLineClass::Set_Points(unsigned int num_points, Vector3 *locs)
100{
101 if (num_points < 2 || !locs) {
102 WWASSERT(0);
103 return;
104 }
105
106 PointLocations.Delete_All();
107 for (unsigned int i=0; i<num_points; i++) {
108 PointLocations.Add(locs[i],num_points);
109 }
110
112}
113
114// These are segment points, and include the start and end point of the
115// entire line. Therefore there must be at least two.
117{
118 return PointLocations.Count();
119}
120
121// Set object-space location for a given point.
122// NOTE: If given position beyond end of point list, do nothing.
123void SegmentedLineClass::Set_Point_Location(unsigned int point_idx, const Vector3 &location)
124{
125 if (point_idx < (unsigned int)PointLocations.Count()) {
126 PointLocations[point_idx] = location;
127 }
129}
130
131// Get object-space location of a given point (if position beyond end of
132// point list, will return 0,0,0).
133void SegmentedLineClass::Get_Point_Location(unsigned int point_idx, Vector3 &loc)
134{
135 if (point_idx < (unsigned int)PointLocations.Count()) {
136 loc.Set(PointLocations[point_idx]);
137 } else {
138 loc.Set(0, 0, 0);
139 }
140}
141
143{
144 PointLocations.Add(location);
145}
146
147void SegmentedLineClass::Delete_Point(unsigned int point_idx)
148{
149 if (point_idx < (unsigned int)PointLocations.Count()) {
150 PointLocations.Delete(point_idx);
151 }
152}
153
154
156{
157 return LineRenderer.Get_Texture();
158}
159
161{
162 return LineRenderer.Get_Shader();
163}
164
166{
167 color.Set(LineRenderer.Get_Color());
168}
169
171{
172 return LineRenderer.Get_Opacity();
173}
174
176{
177 return LineRenderer.Get_Noise_Amplitude();
178}
179
181{
182 return LineRenderer.Get_Merge_Abort_Factor();
183}
184
186{
187 return MaxSubdivisionLevels;
188}
189
191{
192 return LineRenderer.Get_Texture_Mapping_Mode();
193}
194
196{
197 return LineRenderer.Get_Texture_Tile_Factor();
198}
199
201{
202 return LineRenderer.Get_UV_Offset_Rate();
203}
204
206{
207 return LineRenderer.Is_Merge_Intersections();
208}
209
211{
212 return LineRenderer.Is_Freeze_Random();
213}
214
216{
217 return LineRenderer.Is_Sorting_Disabled();
218}
219
221{
222 return LineRenderer.Are_End_Caps_Enabled();
223}
224
226{
227 LineRenderer.Set_Texture(texture);
228}
229
231{
232 LineRenderer.Set_Shader(shader);
233}
234
236{
237 return LineRenderer.Get_Width();
238}
239
241{
242 // Widths need to be clamped because they are not automatically clamped later (like colors and
243 // alphas are).
244 LineRenderer.Set_Width(MAX(width, 0.0f));
245
247}
248
250{
251 LineRenderer.Set_Color(color);
252}
253
255{
256 LineRenderer.Set_Opacity(opacity);
257}
258
260{
261 LineRenderer.Set_Noise_Amplitude(WWMath::Fabs(amplitude));
262
264}
265
267{
268 LineRenderer.Set_Merge_Abort_Factor(factor);
269}
270
272{
273 MaxSubdivisionLevels = MIN(levels, MAX_SEGLINE_SUBDIV_LEVELS);
274
276}
277
279{
280 LineRenderer.Set_Texture_Mapping_Mode(mode);
281}
282
284{
285 LineRenderer.Set_Texture_Tile_Factor(factor);
286}
287
289{
290 LineRenderer.Set_UV_Offset_Rate(rate);
291}
292
294{
295 LineRenderer.Set_Merge_Intersections(onoff);
296}
297
299{
300 LineRenderer.Set_Freeze_Random(onoff);
301}
302
303
305{
306 LineRenderer.Set_Disable_Sorting(onoff);
307}
308
310{
311 LineRenderer.Set_End_Caps(onoff);
312}
313
314/*
315** RenderObjClass interface:
316*/
317
319{
320 return NEW_REF( SegmentedLineClass, (*this));
321}
322
324{
325 int subdivision_factor = 1 << LineRenderer.Get_Current_Subdivision_Level();
326 return 2 * (PointLocations.Count() - 1) * subdivision_factor;
327}
328
330{
331 if (Is_Not_Hidden_At_All() == false) {
332 return ;
333 }
334
335 // Process texture reductions:
336// if (LineRenderer.Peek_Texture()) LineRenderer.Peek_Texture()->Process_Reduction();
337
338 unsigned int sort_level = SORT_LEVEL_NONE;
339
341 sort_level=Get_Shader().Guess_Sort_Level();
342
344
345 WW3D::Add_To_Static_Sort_List(this, sort_level);
346
347 } else
348 Render_Seg_Line(rinfo);
349}
350
352{
353 // Get object-space bounding box and create bounding sphere from it
354 AABoxClass box;
356
357 // Create object-space bounding sphere from the bounding box:
358 sphere.Center = box.Center;
359 sphere.Radius = box.Extent.Length();
360}
361
363{
364 unsigned int num_points = PointLocations.Count();
365
366 // Line must have at least two points to be valid
367
368 if (num_points >= 2) {
369
370 // Find object-space axis-aligned bounding box
371 Vector3 max_coords;
372 Vector3 min_coords;
373 unsigned int i;
374
375 // We create two bounding boxes; one from the points, and if we have random noise
376 // subdivision we create another one from the midpoints and factor the noise amplitude
377 // into the second box, and then combine the two.
378
379 // First bounding box:
380 max_coords = PointLocations[0];
381 min_coords = PointLocations[0];
382 for (i = 1; i < num_points; i++) {
383 max_coords.Update_Max(PointLocations[i]);
384 min_coords.Update_Min(PointLocations[i]);
385 }
386 // Enlarge bounding box by half the width
387 float enlarge_factor = LineRenderer.Get_Width() * 0.5f;
388 Vector3 enlarge_offset;
389 enlarge_offset.Set(enlarge_factor, enlarge_factor, enlarge_factor);
390 max_coords += enlarge_offset;
391 min_coords -= enlarge_offset;
392
393 if (MaxSubdivisionLevels > 0) {
394 // Second bounding box:
395 Vector3 max_coords2;
396 Vector3 min_coords2;
397 Vector3 midpoint = (PointLocations[0] + PointLocations[1]) * 0.5f;
398 max_coords2 = midpoint;
399 min_coords2 = midpoint;
400 for (i = 1; i < num_points - 1; i++) {
401 midpoint = (PointLocations[i] + PointLocations[i + 1]) * 0.5f;
402 max_coords2.Update_Max(midpoint);
403 min_coords2.Update_Min(midpoint);
404 }
405
406 // We ignore the actual number of subdivision levels: we multiply the random noise
407 // amplitude by 2, which is the limit as the number of subdivision levels goes to
408 // infinity.
409 enlarge_factor += (2 * LineRenderer.Get_Noise_Amplitude());
410 enlarge_offset.Set(enlarge_factor, enlarge_factor, enlarge_factor);
411 max_coords2 += enlarge_offset;
412 min_coords2 -= enlarge_offset;
413
414 // Combine the two:
415 max_coords.Update_Max(max_coords2);
416 min_coords.Update_Min(min_coords2);
417 }
418
419 box.Init_Min_Max(min_coords, max_coords);
420
421 } else {
422 // Invalid line - return something
423 box.Init(Vector3(0,0,0),Vector3(1,1,1));
424 }
425}
426
428{
429 // Find the maximum screen dimension of the object in pixels
430 NormalizedScreenArea = Get_Screen_Size(camera);
431
432// // Find and set texture reduction factor
433// Set_Texture_Reduction_Factor(Calculate_Texture_Reduction_Factor(NormalizedScreenArea));
434
435 // Ensure subdivision level is legal
436 unsigned int lvl = LineRenderer.Get_Current_Subdivision_Level();
437 lvl = MIN(lvl, MaxSubdivisionLevels);
438 LineRenderer.Set_Current_Subdivision_Level(lvl);
439
440 // Prepare LOD processing if the line has subdivision enabled:
441 if (MaxSubdivisionLevels > 0) {
442 // Add myself to the LOD optimizer:
444 } else {
445 // Not added to optimizer, need to add cost
447 }
448}
449
451{
452 unsigned int lvl = LineRenderer.Get_Current_Subdivision_Level();
453
454 lvl = MIN(lvl+1,MaxSubdivisionLevels);
455
456 LineRenderer.Set_Current_Subdivision_Level(lvl);
457}
458
460{
461 int lvl = LineRenderer.Get_Current_Subdivision_Level();
462 if (lvl == 0) return;
463 LineRenderer.Set_Current_Subdivision_Level(lvl-1);
464}
465
467{
468 return Get_Num_Polys();
469}
470
472{
473 // If we are at the minimum LOD, we must return AT_MIN_LOD.
474 if (LineRenderer.Get_Current_Subdivision_Level() == 0) {
475 return AT_MIN_LOD;
476 } else {
477 float polycount = (float)Get_Num_Polys();
478 float benefit_factor = 1.0f - (0.5f / (polycount * polycount));
479 return (benefit_factor * NormalizedScreenArea) / Get_Cost();
480 }
481}
482
484{
485 // If we are at the maximum LOD, we must return AT_MIN_LOD.
486 if (LineRenderer.Get_Current_Subdivision_Level() == MaxSubdivisionLevels) {
487 return AT_MAX_LOD;
488 } else {
489 // Assumption: each subdivision level doubles polycount
490 float polycount = 2.0f * (float)Get_Num_Polys();
491 float benefit_factor = 1.0f - (0.5f / (polycount * polycount));
492 // Assumption: Cost() == polycount
493 return (benefit_factor * NormalizedScreenArea) / polycount;
494 }
495}
496
498{
499 lod = MAX(0, lod);
500 lod = MIN(lod, (int)MaxSubdivisionLevels);
501
502 LineRenderer.Set_Current_Subdivision_Level((unsigned int)lod);
503}
504
506{
507 return (int) LineRenderer.Get_Current_Subdivision_Level();
508}
509
511{
512 return (int)MaxSubdivisionLevels;
513}
514/*
515void SegmentedLineClass::Set_Texture_Reduction_Factor(float trf)
516{
517 if (LineRenderer.Peek_Texture()) LineRenderer.Peek_Texture()->Set_Reduction_Factor(trf);
518}*/
519
520
521
523{
524 // Line must have at least two points to be valid
525 if (PointLocations.Count() < 2) return;
526
527 SphereClass bounding_sphere;
528 Get_Obj_Space_Bounding_Sphere(bounding_sphere);
529
530 LineRenderer.Render(
531 rinfo,
532 Transform,
533 PointLocations.Count(),
534 &(PointLocations[0]),
535 bounding_sphere
536 );
537}
538
539
541{
542 if ((Get_Collision_Type() & raytest.CollisionType) == 0) return false;
543
544 bool retval = false;
545
546 //
547 // Check each line segment against the ray
548 //
549 float fraction = 1.0F;
550 for (uint32 index = 1; index < (unsigned int)PointLocations.Count(); index ++)
551 {
552#ifdef ALLOW_TEMPORARIES
553 Vector3 curr_start = Transform * PointLocations[index-1];
554 Vector3 curr_end = Transform * PointLocations[index];
555 LineSegClass line_seg (curr_start, curr_end);
556#else
557 Vector3 curr[2];
558 Transform.mulVector3Array(&PointLocations[index-1], curr, 2);
559 LineSegClass line_seg(curr[0], curr[1]);
560#endif
561
562 Vector3 p0;
563 Vector3 p1;
564 if (raytest.Ray.Find_Intersection (line_seg, &p0, &fraction, &p1, NULL)) {
565
566 //
567 // Determine if the ray was close enough to this line to be
568 // considered intersecting
569 //
570 float dist = (p0 - p1).Length ();
571 if (dist <= LineRenderer.Get_Width() && fraction >= 0 && fraction < raytest.Result->Fraction) {
572 //if (dist <= Width && fraction < raytest.Result->Fraction) {
573 retval = true;
574 break;
575 }
576 }
577 }
578
579 //
580 // Fill in the raytest structure if we were successfull
581 //
582 if (retval) {
583 raytest.Result->Fraction = fraction;
585 raytest.CollidedRenderObj = this;
586 }
587
588 return retval;
589}
590
591
#define NULL
Definition BaseType.h:92
#define WWASSERT
#define SORT_LEVEL_NONE
Definition w3d_file.h:1195
@ SURFACE_TYPE_DEFAULT
Definition w3d_file.h:1075
#define MIN(a, b)
Definition always.h:189
#define MAX(a, b)
Definition always.h:185
unsigned long uint32
Definition bittype.h:46
WWINLINE void Init(const Vector3 &center, const Vector3 &extent)
Definition aabox.h:101
Vector3 Center
Definition aabox.h:123
void Init_Min_Max(const Vector3 &min, const Vector3 &max)
Definition aabox.h:339
Vector3 Extent
Definition aabox.h:124
CastResultStruct * Result
Definition coltest.h:98
RenderObjClass * CollidedRenderObj
Definition coltest.h:100
bool Find_Intersection(const LineSegClass &other_line, Vector3 *p1, float *fraction1, Vector3 *p2, float *fraction2) const
Definition lineseg.cpp:167
static void Add_Object(RenderObjClass *robj)
Definition predlod.cpp:226
static void Add_Cost(float cost)
Definition predlod.h:67
LineSegClass Ray
Definition coltest.h:139
virtual float Get_Screen_Size(CameraClass &camera)
Definition rendobj.cpp:324
virtual int Is_Not_Hidden_At_All(void)
Definition rendobj.h:463
RenderObjClass(void)
Definition rendobj.cpp:170
void Invalidate_Cached_Bounding_Volumes(void) const
Definition rendobj.h:523
RenderObjClass & operator=(const RenderObjClass &)
Definition rendobj.cpp:232
static const float AT_MAX_LOD
Definition rendobj.h:405
Matrix3D Transform
Definition rendobj.h:549
virtual int Get_Collision_Type(void) const
Definition rendobj.h:484
static const float AT_MIN_LOD
Definition rendobj.h:404
virtual float Get_Post_Increment_Value(void) const
Definition segline.cpp:483
Vector2 Get_UV_Offset_Rate(void)
Definition segline.cpp:200
int Are_End_Caps_Enabled(void)
Definition segline.cpp:220
void Set_Shader(ShaderClass shader)
Definition segline.cpp:230
virtual int Get_LOD_Level(void) const
Definition segline.cpp:505
unsigned int Get_Subdivision_Levels(void)
Definition segline.cpp:185
TextureClass * Get_Texture(void)
Definition segline.cpp:155
void Set_Freeze_Random(int onoff)
Definition segline.cpp:298
virtual void Render(RenderInfoClass &rinfo)
Definition segline.cpp:329
void Delete_Point(unsigned int point_idx)
Definition segline.cpp:147
virtual float Get_Value(void) const
Definition segline.cpp:471
virtual void Get_Obj_Space_Bounding_Sphere(SphereClass &sphere) const
Definition segline.cpp:351
virtual void Prepare_LOD(CameraClass &camera)
Definition segline.cpp:427
void Set_UV_Offset_Rate(const Vector2 &rate)
Definition segline.cpp:288
void Set_Color(const Vector3 &color)
Definition segline.cpp:249
void Set_Texture(TextureClass *texture)
Definition segline.cpp:225
float Get_Opacity(void)
Definition segline.cpp:170
void Set_Noise_Amplitude(float amplitude)
Definition segline.cpp:259
int Get_Num_Points(void)
Definition segline.cpp:116
void Reset_Line(void)
Definition segline.cpp:91
int Is_Freeze_Random(void)
Definition segline.cpp:210
virtual void Increment_LOD(void)
Definition segline.cpp:450
virtual RenderObjClass * Clone(void) const
Definition segline.cpp:318
virtual bool Cast_Ray(RayCollisionTestClass &raytest)
Definition segline.cpp:540
void Set_Texture_Mapping_Mode(SegLineRendererClass::TextureMapMode mode)
Definition segline.cpp:278
void Set_Disable_Sorting(int onoff)
Definition segline.cpp:304
virtual void Set_LOD_Level(int lod)
Definition segline.cpp:497
float Get_Noise_Amplitude(void)
Definition segline.cpp:175
SegLineRendererClass::TextureMapMode Get_Texture_Mapping_Mode(void)
Definition segline.cpp:190
void Get_Color(Vector3 &color)
Definition segline.cpp:165
virtual ~SegmentedLineClass(void)
Definition segline.cpp:87
void Set_Texture_Tile_Factor(float factor)
Definition segline.cpp:283
SegmentedLineClass(void)
Definition segline.cpp:58
void Set_Point_Location(unsigned int point_idx, const Vector3 &location)
Definition segline.cpp:123
void Set_Points(unsigned int num_points, Vector3 *locs)
Definition segline.cpp:99
void Get_Point_Location(unsigned int point_idx, Vector3 &loc)
Definition segline.cpp:133
SegmentedLineClass & operator=(const SegmentedLineClass &that)
Definition segline.cpp:72
void Set_Merge_Abort_Factor(float factor)
Definition segline.cpp:266
void Set_Subdivision_Levels(unsigned int levels)
Definition segline.cpp:271
void Render_Seg_Line(RenderInfoClass &rinfo)
Definition segline.cpp:522
virtual int Get_LOD_Count(void) const
Definition segline.cpp:510
void Add_Point(const Vector3 &location)
Definition segline.cpp:142
float Get_Texture_Tile_Factor(void)
Definition segline.cpp:195
ShaderClass Get_Shader(void)
Definition segline.cpp:160
void Set_End_Caps(int onoff)
Definition segline.cpp:309
void Set_Merge_Intersections(int onoff)
Definition segline.cpp:293
virtual float Get_Cost(void) const
Definition segline.cpp:466
float Get_Merge_Abort_Factor(void)
Definition segline.cpp:180
void Set_Opacity(float opacity)
Definition segline.cpp:254
void Set_Width(float width)
Definition segline.cpp:240
int Is_Sorting_Disabled(void)
Definition segline.cpp:215
virtual int Get_Num_Polys(void) const
Definition segline.cpp:323
virtual void Decrement_LOD(void)
Definition segline.cpp:459
int Is_Merge_Intersections(void)
Definition segline.cpp:205
float Get_Width(void)
Definition segline.cpp:235
virtual void Get_Obj_Space_Bounding_Box(AABoxClass &box) const
Definition segline.cpp:362
int Guess_Sort_Level(void) const
Definition shader.cpp:1123
float Radius
Definition sphere.h:91
Vector3 Center
Definition sphere.h:90
WWINLINE void Update_Max(const Vector3 &a)
Definition vector3.h:617
WWINLINE void Update_Min(const Vector3 &a)
Definition vector3.h:597
WWINLINE float Length(void) const
Definition vector3.h:453
WWINLINE void Set(float x, float y, float z)
Definition vector3.h:103
static void Add_To_Static_Sort_List(RenderObjClass *robj, unsigned int sort_level)
Definition ww3d.cpp:1984
static bool Are_Static_Sort_Lists_Enabled(void)
Definition ww3d.h:282
static bool Is_Sorting_Enabled(void)
Definition ww3d.h:220
static WWINLINE float Fabs(float val)
Definition wwmath.h:113
else return(RetVal)
#define NEW_REF(C, P)
Definition refcount.h:62
#define MAX_SEGLINE_SUBDIV_LEVELS
uint32 SurfaceType
Definition castres.h:67