/* ** Command & Conquer Renegade(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ /*************************************************************************** *** 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 *** *************************************************************************** * * * Project Name : G * * * * $Archive:: /VSS_Sync/ww3d2/pointgr.h $* * * * $Author:: Vss_sync $* * * * $Modtime:: 9/12/01 10:01p $* * * * $Revision:: 11 $* * * *-------------------------------------------------------------------------* * Functions: * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #if defined(_MSC_VER) #pragma once #endif #ifndef POINTGR_H #define POINTGR_H #include "sharebuf.h" #include "shader.h" #include "vector4.h" #include "vector3.h" #include "vector2.h" class VertexMaterialClass; class RenderInfoClass; class TextureClass; /* ** PointGroupClass -- a custom object for rendering ** groups of points (such as particle systems). ** It is possible to change mode/number of points/shader/etc. but these ** changes tend to be expensive if done often. Expected usage is to set the ** point location/color/active arrays each frame the object is visible (with ** the same number of points) and perform other changes relatively rarely. ** NOTE: Currently it is implemented using general triangles (1 or 2 per ** point), so it is probably suboptimal for software rasterization devices ** (which would probably perform better with some kind of blit/sprite code). */ class PointGroupClass { public: enum PointModeEnum { TRIS, // each point is a triangle QUADS, // each point is a quad formed out of two triangles SCREENSPACE // each point is a tri placed to affect certain pixels (should be used with 2D camera) }; enum FlagsType { TRANSFORM, // transform points w. modelview matrix (worldspace points) }; PointGroupClass(void); virtual ~PointGroupClass(void); PointGroupClass & operator = (const PointGroupClass & that); // PointGroupClass interface: void Set_Arrays(ShareBufferClass *locs, ShareBufferClass *diffuse = NULL, ShareBufferClass *apt = NULL, ShareBufferClass *sizes = NULL, ShareBufferClass *orientations = NULL, ShareBufferClass *frames = NULL, int active_point_count = -1, float vpxmin = 0.0f, float vpymin = 0.0f, float vpxmax = 0.0f, float vpymax = 0.0f); void Set_Point_Size(float size); float Get_Point_Size(void); void Set_Point_Color(Vector3 color); Vector3 Get_Point_Color(void); void Set_Point_Alpha(float alpha); float Get_Point_Alpha(void); void Set_Point_Orientation(unsigned char orientation); unsigned char Get_Point_Orientation(void); void Set_Point_Frame(unsigned char frame); unsigned char Get_Point_Frame(void); void Set_Point_Mode(PointModeEnum mode); PointModeEnum Get_Point_Mode(void); void Set_Flag(FlagsType flag, bool onoff); int Get_Flag(FlagsType flag); void Set_Texture(TextureClass* texture); TextureClass * Get_Texture(void); TextureClass * Peek_Texture(void); void Set_Shader(ShaderClass shader); ShaderClass Get_Shader(void); // The frame property is taken from a set of possible frames. The rows/columns in the frame // texture determine the number of possible frames. Since it must be a power of 2, we represent // it as its log base 2. This number cannot be greater than 4 (which corresponds to a 16x16 // square of frames, i.e. 256 frames). unsigned char Get_Frame_Row_Column_Count_Log2(void); void Set_Frame_Row_Column_Count_Log2(unsigned char frccl2); int Get_Polygon_Count(void); void Render(RenderInfoClass &rinfo); protected: // Update arrays. void Update_Arrays(Vector3 *point_loc, Vector4 *point_diffuse, float *point_size, unsigned char *point_orientation, unsigned char *point_frame, int active_points, int total_points, int &vnum, int &pnum); // These shared buffers are used for communication to the point group - to // pass point locations, colors and enables. The location and color arrays // are 'compressed' using the active point table (if present) and then // are processed into other arrays which are passed to the GERD. // SR rather than WWMath types are used so Vector Processors can be used. // The arrays override the default value if present. // The orientation and frame properties are "index properties": they select one out of a small // group of possibilities for each point. // Orientation: this is the 2D rotation of the point about its center. There are 256 discrete // orientations. The unit circle is evenly subdivided 256 times to create the set of // orientations. The reason we discretize orientation is for performance: this way we can // precalculate vertex offsets. // Frame: the texture is divided into a 2D square grid, and each point uses one grid square // instead of the whole texture. The number of possible frames is not invariant - it depends // on the number of rows / columns in the grid. The reason we do this instead of having // different textures is to avoid texture state changes. Also for performance reasons, the // number of possible frames must be a power of two - for this reason the number of frame rows // and columns, orientations, etc. are represented as the log base 2 of the actual number. ShareBufferClass * PointLoc; // World/cameraspace point locs ShareBufferClass * PointDiffuse; // (NULL if not used) RGBA values ShareBufferClass * APT; // (NULL if not used) active point table ShareBufferClass * PointSize; // (NULL if not used) size override table ShareBufferClass * PointOrientation; // (NULL if not used) orientation indices ShareBufferClass * PointFrame; // (NULL if not used) frame indices int PointCount; // Active (if APT) or total point count // See comments for Get/Set_Frame_Row_Column_Count_Log2 above unsigned char FrameRowColumnCountLog2; // MUST be equal or lesser than 4 // These parameters are passed to the GERD: TextureClass* Texture; ShaderClass Shader; // (default created in CTor) // Internal state: PointModeEnum PointMode; // are points tris or quads? unsigned int Flags; // operation control flags float DefaultPointSize; // point size (size array overrides if present) Vector3 DefaultPointColor; // point color (color array overrides if present) float DefaultPointAlpha; // point alpha (alpha array overrides if present) unsigned char DefaultPointOrientation;// point orientation (orientation array overrides if present) unsigned char DefaultPointFrame; // point texture frame (frame array overrides if present) // View plane rectangle (only used in SCREENSPACE mode - set by Set_Arrays // and used in Update_GERD_Arrays). float VPXMin; float VPYMin; float VPXMax; float VPYMax; // Static stuff: // For performance / memory reasons we prepare vertex location and UV // arrays for various orientations and texture frames, as static data // members of this class. This avoids the need to create such arrays over // again for each object. The values in the UV arrays are used as-is, the // values in the location arrays normally need to be scaled to the point // sizes and added to the point location before use. We have distinct sets // of arrays for each point mode. // There are tables of vertex positions for each of triangle and quad mode // with 256 discrete orientations. Each entry contains 3 (for triangle // mode) or 4 (for quad mode) Vector3s. // There are five tables of texture UVs for each of triangle and quad mode: // with 1x1(1), 2x2(4), 4x4(16), 8x8(64) and 16x16(256) frames. Each entry // contains 3 (for triangle mode) or 4 (for quad mode) Vector2s. // In addition, there is one array of vertex positions for screenspace mode // with 2 entries (for size 1 and size 2). Each entry contains 3 Vector3s. // the Init function (which is called by WW3D::Init()) creates these // arrays, and the Shutdown function (which is called by WW3D::Shutdown() // releases them. public: static void _Init(void); static void _Shutdown(void); private: static Vector3 _TriVertexLocationOrientationTable[256][3]; static Vector3 _QuadVertexLocationOrientationTable[256][4]; static Vector3 _ScreenspaceVertexLocationSizeTable[2][3]; static Vector2 *_TriVertexUVFrameTable[5]; static Vector2 *_QuadVertexUVFrameTable[5]; static VertexMaterialClass *PointMaterial; }; #endif