aboutsummaryrefslogtreecommitdiff
path: root/src/parsec/g_planet.cpp
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@gmail.com>2026-08-24 11:16:07 +0200
committerFelix Morgner <felix.morgner@gmail.com>2026-08-24 11:16:07 +0200
commitc068f22329d5cc722622a2183bbb22eef2093df7 (patch)
tree12d56c1aede67988a55e241364606bfbb4dba933 /src/parsec/g_planet.cpp
downloadopenparsec-main.tar.xz
openparsec-main.zip
initial importHEADmain
Diffstat (limited to 'src/parsec/g_planet.cpp')
-rw-r--r--src/parsec/g_planet.cpp573
1 files changed, 573 insertions, 0 deletions
diff --git a/src/parsec/g_planet.cpp b/src/parsec/g_planet.cpp
new file mode 100644
index 0000000..37f0f16
--- /dev/null
+++ b/src/parsec/g_planet.cpp
@@ -0,0 +1,573 @@
+/*
+ * PARSEC - Planet Custom Object
+ *
+ * $Author: uberlinuxguy $ - $Date: 2004/09/26 03:43:36 $
+ *
+ * Orginally written by:
+ * Copyright (c) Andreas Varga <sid@parsec.org> 2000
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+// C library
+#include <math.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// compilation flags/debug support
+#include "config.h"
+#include "debug.h"
+
+// general definitions
+#include "general.h"
+#include "objstruc.h"
+
+// global externals
+#include "globals.h"
+
+// subsystem headers
+#include "aud_defs.h"
+#include "net_defs.h"
+#include "sys_defs.h"
+#include "vid_defs.h"
+
+// drawing subsystem
+#include "d_font.h"
+#include "d_iter.h"
+#include "d_misc.h"
+
+// rendering subsystem
+#include "r_sfx.h"
+
+// mathematics header
+#include "utl_math.h"
+
+// model header
+#include "utl_model.h"
+
+// local module header
+#include "g_planet.h"
+
+// proprietary module headers
+#include "con_info.h"
+#include "e_callbk.h"
+#include "e_color.h"
+#include "e_supp.h"
+#include "g_supp.h"
+#include "h_supp.h"
+#include "net_serv.h"
+#include "obj_clas.h"
+#include "obj_creg.h"
+#include "obj_ctrl.h"
+#include "obj_cust.h"
+#include "obj_xtra.h"
+#include "part_api.h"
+
+
+// flags
+//#define ORBIT_ANIMATION
+//#define SHIP_ORBIT_ANIMATION
+
+
+// generic string paste area --------------------------------------------------
+//
+#define PASTE_STR_LEN 255
+static char paste_str[ PASTE_STR_LEN + 1 ];
+
+
+// offset definitions into the Planet -----------------------------------------
+//
+#define OFS_ROTSPEED offsetof( Planet, RotSpeed )
+#define OFS_ORBITSPEED offsetof( Planet, OrbitSpeed )
+#define OFS_ORBITRADIUS offsetof( Planet, OrbitRadius )
+#define OFS_NAME offsetof( Planet, Name )
+#define OFS_HASRING offsetof( Planet, HasRing )
+#define OFS_RINGOUTERRADIUS offsetof( Planet, RingOuterRadius )
+#define OFS_RINGINNERRADIUS offsetof( Planet, RingInnerRadius )
+#define OFS_RINGTEXNAME offsetof( Planet, RingTexName )
+
+
+// list of console-accessible properties --------------------------------------
+//
+PRIVATE
+proplist_s Planet_PropList[] = {
+
+
+ { "rotspeed", OFS_ROTSPEED, 0, 0xffff, PROPTYPE_INT, NULL },
+ { "orbitspeed", OFS_ORBITSPEED, 0, 0xffff, PROPTYPE_INT, NULL },
+ { "orbitradius", OFS_ORBITRADIUS, 0x10000, 0x4000000, PROPTYPE_FLOAT, NULL },
+ { "name", OFS_NAME, 0, MAX_PLANET_NAME, PROPTYPE_STRING, NULL },
+ { "hasring", OFS_HASRING, 0x0, 0x1, PROPTYPE_INT, NULL },
+ { "ringouterradius", OFS_RINGOUTERRADIUS, 0x10000, 0x4000000, PROPTYPE_FLOAT, NULL },
+ { "ringinnerradius", OFS_RINGINNERRADIUS, 0x10000, 0x4000000, PROPTYPE_FLOAT, NULL },
+ { "ringtexname", OFS_RINGTEXNAME, 0, MAX_RING_TEXNAME, PROPTYPE_STRING, NULL },
+
+ { NULL, 0, 0, 0, 0, NULL },
+};
+
+
+// type fields init function for planet ---------------------------------------
+//
+PRIVATE
+void PlanetInitType( CustomObject *base )
+{
+ ASSERT( base != NULL );
+
+ Planet *planet = (Planet *) base;
+
+ planet->RotSpeed = 0x0001;
+ planet->CurOrbitPos = 0;
+ planet->OrbitSpeed = 0x0001;
+ planet->OrbitRadius = 3000000;
+ planet->OrbitParent = NULL;
+ planet->HasRing = FALSE;
+ planet->RingOuterRadius = FLOAT_TO_GEOMV( 600.0f );
+ planet->RingInnerRadius = FLOAT_TO_GEOMV( 300.0f );
+
+ strncpy( planet->RingTexName, PLANET_RING_TEXTURE, MAX_RING_TEXNAME );
+ planet->RingTexName[ MAX_RING_TEXNAME ] = 0;
+
+ planet->RingTexture = NULL;
+
+ planet->NumOrbitShips = 0;
+}
+
+
+static float orbit_depth = 1.0f;
+
+
+// draw planet rings ----------------------------------------------------------
+//
+void PlanetDraw_Rings( Planet *planet )
+{
+ // create vertex array
+ IterArray3 *itarray = (IterArray3 *) ALLOCMEM(
+ (size_t)&((IterArray3*)0)->Vtxs[ PLANET_RING_SEGMENTS * 2 ] );
+ if ( itarray == NULL )
+ OUTOFMEM( 0 );
+
+ itarray->NumVerts = PLANET_RING_SEGMENTS * 2;
+ itarray->arrayinfo = ITERARRAY_USE_COLOR |
+ ITERARRAY_USE_TEXTURE | ITERARRAY_GLOBAL_TEXTURE;
+ itarray->flags = ITERFLAG_Z_DIV_XYZ | ITERFLAG_Z_DIV_UVW |
+ ITERFLAG_Z_TO_DEPTH;
+ itarray->itertype = iter_texrgba | iter_alphablend;
+ itarray->raststate = rast_zcompare/*rast_zbuffer */| rast_texclamp |
+ rast_chromakeyoff;
+ itarray->rastmask = rast_nomask;
+ itarray->texmap = planet->RingTexture;
+
+ bams_t angleoffs = BAMS_DEG360 / PLANET_RING_SEGMENTS;
+ int seg = 0;
+ for ( seg = 0; seg < PLANET_RING_SEGMENTS; seg++ ) {
+
+ int vid = seg * 2;
+
+ bams_t angle = seg * angleoffs;
+
+ sincosval_s sincos;
+
+ GetSinCos( angle, &sincos );
+
+ byte r = 110;
+ byte g = 80;
+ byte b = 180;
+ byte a = 180;
+
+ // fill vertex array
+ itarray->Vtxs[ vid ].X = GEOMV_MUL( planet->BoundingSphere + planet->RingOuterRadius, sincos.cosval );
+ itarray->Vtxs[ vid ].Y = GEOMV_0;
+ itarray->Vtxs[ vid ].Z = GEOMV_MUL( planet->BoundingSphere + planet->RingOuterRadius, sincos.sinval );
+ itarray->Vtxs[ vid ].W = GEOMV_1;
+ itarray->Vtxs[ vid ].U = 0;
+ itarray->Vtxs[ vid ].V = 0;
+ itarray->Vtxs[ vid ].R = r;
+ itarray->Vtxs[ vid ].G = g;
+ itarray->Vtxs[ vid ].B = b;
+ itarray->Vtxs[ vid ].A = a;
+
+ itarray->Vtxs[ vid + 1 ].X = GEOMV_MUL( planet->BoundingSphere + planet->RingInnerRadius, sincos.cosval );
+ itarray->Vtxs[ vid + 1 ].Y = GEOMV_0;
+ itarray->Vtxs[ vid + 1 ].Z = GEOMV_MUL( planet->BoundingSphere + planet->RingInnerRadius, sincos.sinval );
+ itarray->Vtxs[ vid + 1 ].W = GEOMV_1;
+ itarray->Vtxs[ vid + 1 ].U = 0;
+ itarray->Vtxs[ vid + 1 ].V = PLANET_RING_TEX_HEIGHT;
+ itarray->Vtxs[ vid + 1 ].R = r;
+ itarray->Vtxs[ vid + 1 ].G = g;
+ itarray->Vtxs[ vid + 1 ].B = b;
+ itarray->Vtxs[ vid + 1 ].A = a;
+ }
+
+ size_t numtriindxs = PLANET_RING_SEGMENTS * 6;
+
+ dword *vindxs = (dword *) ALLOCMEM( numtriindxs * sizeof( dword ) );
+ if ( vindxs == NULL )
+ OUTOFMEM( 0 );
+
+ int dstindx = 0;
+ int srcindx = 0;
+
+ // store all strip indexes but last
+ for ( seg = 0; seg < PLANET_RING_SEGMENTS - 1; seg++ ) {
+
+ vindxs[ dstindx + 0 ] = srcindx;
+ vindxs[ dstindx + 1 ] = srcindx + 1;
+ vindxs[ dstindx + 2 ] = srcindx + 3;
+ dstindx += 3;
+
+ vindxs[ dstindx + 0 ] = srcindx;
+ vindxs[ dstindx + 1 ] = srcindx + 2;
+ vindxs[ dstindx + 2 ] = srcindx + 3;
+ dstindx += 3;
+
+ srcindx += 2;
+ }
+
+ // store last strip index
+ vindxs[ dstindx + 0 ] = srcindx;
+ vindxs[ dstindx + 1 ] = srcindx + 1;
+ vindxs[ dstindx + 2 ] = 1;
+ dstindx += 3;
+
+ vindxs[ dstindx + 0 ] = srcindx;
+ vindxs[ dstindx + 1 ] = 0;
+ vindxs[ dstindx + 2 ] = 1;
+ dstindx += 3;
+
+ // calculate transformation matrix
+ MtxMtxMUL( ViewCamera, planet->ObjPosition, DestXmatrx );
+
+ // setup transformation matrix
+ D_LoadIterMatrix( DestXmatrx );
+
+ // lock array
+ D_LockIterArray3( itarray, 0, itarray->NumVerts );
+
+ // draw indexed triangles in a single call (no far-plane clipping!)
+ D_DrawIterArrayIndexed(
+ ITERARRAY_MODE_TRIANGLES, numtriindxs, vindxs, 0x3d );
+
+ // unlock array
+ D_UnlockIterArray();
+
+ // restore identity transformation
+ D_LoadIterMatrix( NULL );
+
+ // free vertex index array
+ FREEMEM( vindxs );
+
+ // free vertex array
+ FREEMEM( itarray );
+}
+
+
+// planet effect drawing callback ---------------------------------------------
+//
+int PlanetDraw( void *param )
+{
+ ASSERT( param != NULL );
+ Planet *planet = (Planet *) param;
+
+ // draw sphere
+ R_DrawPlanet( planet );
+
+ //TODO:
+ // move all drawing together with a single interface.
+
+ if ( planet->HasRing ) {
+ //PlanetDraw_Rings( planet );
+ }
+
+ if ( orbit_depth == 1.0f ) {
+ return FALSE;
+ }
+
+ colrgba_s glowcol;
+
+ int val = (int)(255 * 4 - ( orbit_depth * 255 ) * 4);
+
+ glowcol.R = ( val > 255 ) ? 255 : val;
+ glowcol.G = 0;
+ glowcol.B = 0;
+ glowcol.A = glowcol.R;
+
+ VIDs_SetScreenToColor( glowcol );
+
+ orbit_depth = 1.0f;
+
+ return TRUE;
+}
+
+
+// planet constructor (class instantiation) -----------------------------------
+//
+PRIVATE
+void PlanetInstantiate( CustomObject *base )
+{
+ ASSERT( base != NULL );
+ Planet *planet = (Planet *) base;
+
+ planet->RingTexture = FetchTextureMap( planet->RingTexName );
+ if ( planet->RingTexture == NULL ) {
+ MSGOUT( "texture '%s' was not found.", planet->RingTexName );
+ }
+}
+
+
+// callback type and flags ----------------------------------------------------
+//
+//static int callback_type = CBTYPE_DRAW_CUSTOM_ITER | CBFLAG_REMOVE;
+static int callback_type = CBTYPE_DRAW_OBJECTS | CBFLAG_REMOVE;
+
+
+// planet animation callback --------------------------------------------------
+//
+PRIVATE
+int PlanetAnimate( CustomObject *base )
+{
+ ASSERT( base != NULL );
+ Planet *planet = (Planet *) base;
+
+ planet->CullMask = 0x00; // no far plane clipping
+
+
+
+ // simply rotate around Z
+ ObjRotZ( planet->ObjPosition, planet->RotSpeed * CurScreenRefFrames );
+ return true;
+
+ // Oribit code to orbit around an object.
+ // get orbit center object, center is (0,0,0) if object pointer is null
+ Vector3 orbitcenter;
+
+ if ( planet->OrbitParent == NULL ) {
+
+
+ return true;
+ /*
+ orbitcenter.X = GEOMV_0;
+ orbitcenter.Y = GEOMV_0;
+ orbitcenter.Z = GEOMV_0;
+ */
+ } else {
+
+ orbitcenter.X = planet->ObjPosition[ 0 ][ 3 ];
+ orbitcenter.Y = planet->ObjPosition[ 1 ][ 3 ];
+ orbitcenter.Z = planet->ObjPosition[ 2 ][ 3 ];
+ }
+
+ planet->CurOrbitPos += ( planet->OrbitSpeed * CurScreenRefFrames );
+
+ sincosval_s sincos;
+
+ GetSinCos( planet->CurOrbitPos, &sincos );
+
+ planet->ObjPosition[ 0 ][ 3 ] = orbitcenter.X + GEOMV_MUL( sincos.sinval, planet->OrbitRadius );
+ planet->ObjPosition[ 1 ][ 3 ] = orbitcenter.Y + GEOMV_MUL( sincos.cosval, planet->OrbitRadius );
+ planet->ObjPosition[ 2 ][ 3 ] = orbitcenter.Z;
+
+
+
+ return TRUE;
+}
+
+
+// planet destructor (instance destruction) -----------------------------------
+//
+PRIVATE
+void PlanetDestroy( CustomObject *base )
+{
+ ASSERT( base != NULL );
+ Planet *planet = (Planet *) base;
+
+ // ensure pending callbacks are destroyed to avoid
+ // calling them with invalid pointers
+ int numremoved = CALLBACK_DestroyCallback( callback_type, (void *) base );
+ ASSERT( numremoved <= 1 );
+}
+
+
+// planet collision callback --------------------------------------------------
+//
+PRIVATE
+int PlanetCollide( CustomObject *base )
+{
+ ASSERT( base != NULL );
+ Planet *planet = (Planet *) base;
+
+#if 0
+
+ Vector3 diff;
+ diff.X = MyShip->ObjPosition[ 0 ][ 3 ] - planet->ObjPosition[ 0 ][ 3 ];
+ diff.Y = MyShip->ObjPosition[ 1 ][ 3 ] - planet->ObjPosition[ 1 ][ 3 ];
+ diff.Z = MyShip->ObjPosition[ 2 ][ 3 ] - planet->ObjPosition[ 2 ][ 3 ];
+
+ geomv_t orbit_dist = VctLenX( &diff );
+
+ if ( orbit_dist <= ( planet->BoundingSphere + MyShip->BoundingSphere ) ) {
+
+ //FIXME: this must be triggered by the server
+
+ // trigger explosion
+ KillDurationWeapons( MyShip );
+ OBJ_CreateShipExtras( MyShip );
+
+ AUD_PlayerKilled();
+ ShipDowned = TRUE;
+
+ return TRUE;
+ }
+
+ geomv_t maxorbitdistance = GEOMV_MUL( INT_TO_GEOMV( 10 ), MyShip->BoundingSphere );
+
+ if ( orbit_dist <= ( planet->BoundingSphere + maxorbitdistance ) ) {
+
+ if ( MyShip->Orbit != planet ) {
+
+ ShowMessage( "entering orbit" );
+
+ MyShip->Orbit = (GenObject *) planet;
+ planet->NumOrbitShips++;
+ }
+
+ // orbit_depth == 1.0 if ship is in outermost orbit distance
+ orbit_depth = GEOMV_TO_FLOAT( GEOMV_DIV( orbit_dist, planet->BoundingSphere + maxorbitdistance ) );
+
+#ifdef SHIP_ORBIT_ANIMATION
+
+ // move ship along orbit if speed is zero
+ if ( MyShip->CurSpeed == 0 ) {
+
+ float orbit_rot = asin( GEOMV_TO_FLOAT( GEOMV_DIV( diff.Z, orbit_dist ) ) );
+
+ orbit_rot += 10 * CurScreenRefFrames;
+
+ MSGOUT( "rot: %f", orbit_rot );
+
+ sincosval_s sincos;
+
+ GetSinCos( orbit_rot, &sincos );
+
+ MSGOUT( "sin: %f, cos: %f", sincos.sinval, sincos.cosval );
+
+ Xmatrx curobjpos;
+ CalcOrthoInverse( ShipViewCamera, curobjpos );
+
+ Vector3 offs, toffs;
+ offs.X = ( planet->ObjPosition[ 0 ][ 3 ] + GEOMV_MUL( sincos.cosval, orbit_dist ) ) - curobjpos[ 0 ][ 3 ];
+ offs.Y = GEOMV_0;
+ offs.Z = ( planet->ObjPosition[ 2 ][ 3 ] + GEOMV_MUL( sincos.sinval, orbit_dist ) ) - curobjpos[ 2 ][ 3 ];
+
+ // apply transformation
+ MtxVctMULt( ShipViewCamera, &offs, &toffs );
+
+ ShipViewCamera[ 0 ][ 3 ] -= INT_TO_GEOMV( GEOMV_TO_INT( toffs.X ) );
+ ShipViewCamera[ 1 ][ 3 ] -= INT_TO_GEOMV( GEOMV_TO_INT( toffs.Y ) );
+ ShipViewCamera[ 2 ][ 3 ] -= INT_TO_GEOMV( GEOMV_TO_INT( toffs.Z ) );
+
+ PseudoStarMovement[ 0 ][ 3 ] -= INT_TO_GEOMV( GEOMV_TO_INT( toffs.X ) );
+ PseudoStarMovement[ 1 ][ 3 ] -= INT_TO_GEOMV( GEOMV_TO_INT( toffs.Y ) );
+ PseudoStarMovement[ 2 ][ 3 ] -= INT_TO_GEOMV( GEOMV_TO_INT( toffs.Z ) );
+
+/*
+ static bams_t orbit_rot = 0;
+
+ sincosval_s sincos;
+
+ GetSinCos( orbit_rot, &sincos );
+
+ Xmatrx curobjpos;
+ CalcOrthoInverse( ShipViewCamera, curobjpos );
+
+ Vector3 offs, toffs;
+ offs.X = ( planet->ObjPosition[ 0 ][ 3 ] + GEOMV_MUL( sincos.cosval, orbit_dist ) ) - curobjpos[ 0 ][ 3 ];
+ offs.Y = GEOMV_0;
+ offs.Z = ( planet->ObjPosition[ 2 ][ 3 ] + GEOMV_MUL( sincos.sinval, orbit_dist ) ) - curobjpos[ 2 ][ 3 ];
+
+ // apply transformation
+ MtxVctMULt( ShipViewCamera, &offs, &toffs );
+
+ ShipViewCamera[ 0 ][ 3 ] -= INT_TO_GEOMV( GEOMV_TO_INT( toffs.X ) );
+ ShipViewCamera[ 1 ][ 3 ] -= INT_TO_GEOMV( GEOMV_TO_INT( toffs.Y ) );
+ ShipViewCamera[ 2 ][ 3 ] -= INT_TO_GEOMV( GEOMV_TO_INT( toffs.Z ) );
+
+ PseudoStarMovement[ 0 ][ 3 ] -= INT_TO_GEOMV( GEOMV_TO_INT( toffs.X ) );
+ PseudoStarMovement[ 1 ][ 3 ] -= INT_TO_GEOMV( GEOMV_TO_INT( toffs.Y ) );
+ PseudoStarMovement[ 2 ][ 3 ] -= INT_TO_GEOMV( GEOMV_TO_INT( toffs.Z ) );
+
+// orbit_rot += CurScreenRefFrames;
+*/
+
+ }
+
+#endif // SHIP_ORBIT_ANIMATION
+
+ } else {
+
+ if ( MyShip->Orbit == planet ) {
+
+ ShowMessage( "leaving orbit" );
+
+ MyShip->Orbit = NULL;
+ planet->NumOrbitShips--;
+ }
+ }
+
+#endif
+
+ // register the drawing callback for the red overlay
+ CALLBACK_RegisterCallback( callback_type, PlanetDraw, (void *) base );
+
+ return TRUE;
+}
+
+
+// register object type for planet --------------------------------------------
+//
+PRIVATE
+void PlanetRegisterCustomType()
+{
+ custom_type_info_s info;
+ memset( &info, 0, sizeof( info ) );
+
+ info.type_name = "planet";
+ info.type_id = 0x00000000;
+ info.type_size = sizeof( Planet );
+ info.type_template = NULL;
+ info.type_flags = CUSTOM_TYPE_DEFAULT;
+ info.callback_init = PlanetInitType;
+ info.callback_instant = PlanetInstantiate;
+ info.callback_destroy = PlanetDestroy;
+ info.callback_animate = PlanetAnimate;
+ info.callback_collide = PlanetCollide;
+ info.callback_notify = NULL;
+ info.callback_persist = NULL;
+
+ OBJ_RegisterCustomType( &info );
+ CON_RegisterCustomType( info.type_id, Planet_PropList );
+}
+
+
+// module registration function -----------------------------------------------
+//
+REGISTER_MODULE( G_PLANET )
+{
+ // register type
+ PlanetRegisterCustomType();
+}
+
+