Main Page | Alphabetical List | Compound List | File List | Compound Members | File Members

electric.c

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  ELECTRIC.C                                                                          */
00003 /*                                                                                      */
00004 /*  Author: Eli Boling                                                                  */
00005 /*  Description: Animated electrical bolt special effect implementation                 */
00006 /*                                                                                      */
00007 /*  The contents of this file are subject to the Genesis3D Public License               */
00008 /*  Version 1.01 (the "License"); you may not use this file except in                   */
00009 /*  compliance with the License. You may obtain a copy of the License at                */
00010 /*  http://www.genesis3d.com                                                            */
00011 /*                                                                                      */
00012 /*  Software distributed under the License is distributed on an "AS IS"                 */
00013 /*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
00014 /*  the License for the specific language governing rights and limitations              */
00015 /*  under the License.                                                                  */
00016 /*                                                                                      */
00017 /*  The Original Code is Genesis3D, released March 25, 1999.                            */
00018 /*Genesis3D Version 1.1 released November 15, 1999                            */
00019 /*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */
00020 /*                                                                                      */
00021 /****************************************************************************************/
00022 #include        <windows.h>
00023 #include        <math.h>
00024 #include        <assert.h>
00025 
00026 #include        "genesis.h"
00027 #include        "ErrorLog.h"
00028 
00029 #include        "Electric.h"
00030 #include        "ram.h"
00031 
00032 static  int             logBase2(int n)
00033 {
00034         int     i = 0;
00035 
00036         assert(n != 0);
00037 
00038         while   (!(n & 1))
00039         {
00040                 n = n >> 1;
00041                 i++;
00042         }
00043 
00044         assert((n & ~1) == 0);
00045 
00046         return i;
00047 }
00048 
00049 static  geBoolean       IsPowerOf2(int n)
00050 {
00051         if      (n == 0)
00052                 return GE_TRUE;
00053 
00054         while   (!(n & 1))
00055                 n = n >> 1;
00056 
00057         if      (n & ~1)
00058                 return GE_FALSE;
00059 
00060         return GE_TRUE;
00061 }
00062 
00063 _Electric_BoltEffect * _Electric_BoltEffectCreate(
00064         int NumPolys,
00065         int Width,
00066         geFloat Wildness)
00067 {
00068         _Electric_BoltEffect *  be;
00069         GE_RGBA                                 color;
00070 
00071         assert(Wildness >= 0.0f && Wildness <= 1.0f);
00072 
00073         /* Asserts power of 2 */
00074         logBase2(NumPolys);
00075 
00076         be = (_Electric_BoltEffect *)geRam_Allocate(sizeof(*be));
00077         if      (!be)
00078                 return be;
00079 
00080         memset(be, 0, sizeof(*be));
00081 
00082         be->beCenterPoints = (geVec3d *)geRam_Allocate(sizeof(*be->beCenterPoints) * (NumPolys + 1));
00083         if      (!be->beCenterPoints)
00084                 goto fail;
00085 
00086         be->beNumPoints = NumPolys;
00087         be->beWildness  = Wildness;
00088         be->beWidth             = Width;
00089 
00090         color.r = 160.0f;
00091         color.g = 160.0f;
00092         color.b = 255.0f;
00093         _Electric_BoltEffectSetColorInfo(be, &color, ELECTRIC_BOLT_BLUEDOMINANT);
00094 
00095         return be;
00096 
00097 fail:
00098         if      (be->beCenterPoints)
00099                 geRam_Free(be->beCenterPoints);
00100         if (be)
00101                 geRam_Free(be);
00102 
00103         return NULL;
00104 }
00105 
00106 void _Electric_BoltEffectDestroy(_Electric_BoltEffect *Effect)
00107 {
00108         geRam_Free(Effect->beCenterPoints);
00109         geRam_Free(Effect);
00110 }
00111 
00112 static  geFloat GaussRand(void)
00113 {
00114         int     i;
00115         int     r;
00116 
00117         r = 0;
00118 
00119         for     (i = 0; i < 6; i++)
00120                 r = r + rand() - rand();
00121 
00122         return (geFloat)r / ((geFloat)RAND_MAX * 6.0f);
00123 }
00124 
00125 static  void    subdivide(
00126         _Electric_BoltEffect *  be,
00127         const geVec3d *                 start,
00128         const geVec3d *                 end,
00129         geFloat                                 s,
00130         int                                     n)
00131 {
00132         geVec3d tmp;
00133 
00134         if      (n == 0)
00135         {
00136                 be->beCurrentPoint++;
00137                 *be->beCurrentPoint = *end;
00138                 return;
00139         }
00140         
00141         tmp.X = (end->X + start->X) / 2 + s * GaussRand();
00142         tmp.Y = (end->Y + start->Y) / 2 + s * GaussRand();
00143         tmp.Z = (end->Z + start->Z) / 2 + s * GaussRand();
00144         subdivide(be,  start, &tmp, s / 2, n - 1);
00145         subdivide(be, &tmp,    end, s / 2, n - 1);
00146 }
00147 
00148 #define LIGHTNINGWIDTH 8.0f
00149 
00150 static  void    genLightning(
00151         _Electric_BoltEffect *  be,
00152         int                                     RangeLow,
00153         int                                     RangeHigh,
00154         const geVec3d *                 start,
00155         const geVec3d *                 end)
00156 {
00157         geFloat length;
00158         int             seed;
00159 
00160         assert(be);
00161         assert(start);
00162         assert(end);
00163         assert(RangeHigh > RangeLow);
00164         assert(IsPowerOf2(RangeHigh - RangeLow));
00165 
00166         /* Manhattan length is good enough for this */
00167         length = (geFloat)(fabs(start->X - end->X) +
00168                                                 fabs(start->Y - end->Y) +
00169                                                 fabs(start->Z - end->Z));
00170 
00171         seed = rand();
00172 
00173         srand(seed);
00174         be->beCurrentPoint                                      = be->beCenterPoints + RangeLow;
00175         be->beCenterPoints[RangeLow]            = *start;
00176         be->beCenterPoints[RangeHigh]           = *end;
00177         subdivide(be, start, end, length * be->beWildness, logBase2(RangeHigh - RangeLow));
00178 }
00179 
00180 void _Electric_BoltEffectSetColorInfo(
00181         _Electric_BoltEffect *  Effect,
00182         GE_RGBA *                               BaseColor,
00183         int                                             DominantColor)
00184 {
00185         Effect->beBaseColors[0]         = BaseColor->r;
00186         Effect->beBaseColors[1]         = BaseColor->g;
00187         Effect->beBaseColors[2]         = BaseColor->b;
00188         Effect->beCurrentColors[0]      = BaseColor->r;
00189         Effect->beCurrentColors[1]      = BaseColor->g;
00190         Effect->beCurrentColors[2]      = BaseColor->b;
00191         Effect->beDominantColor         = DominantColor;
00192 }
00193 
00194 void _Electric_BoltEffectAnimate(
00195         _Electric_BoltEffect *  Effect,
00196         const geVec3d *                 start,
00197         const geVec3d *                 end)
00198 {
00199         int             dominant;
00200         int             nonDominant1;
00201         int             nonDominant2;
00202         geVec3d SubdivideStart;
00203         geVec3d SubdivideEnd;
00204         int             LowIndex;
00205         int             HighIndex;
00206 
00207         Effect->beStart = *start;
00208         Effect->beEnd   = *end;
00209 
00210         dominant = Effect->beDominantColor;
00211         nonDominant1 = (dominant + 1) % 3;
00212         nonDominant2 = (dominant + 2) % 3;
00213         if      (Effect->beBaseColors[nonDominant1] == Effect->beCurrentColors[nonDominant1])
00214         {
00215                 int     DecayRate;
00216                 int     Spike;
00217 
00218                 DecayRate = rand() % (int)(Effect->beBaseColors[dominant] - Effect->beBaseColors[nonDominant1]);
00219                 DecayRate = max(DecayRate, 5);
00220                 Effect->beDecayRate = DecayRate;
00221                 if      (Effect->beBaseColors[nonDominant1] >= 1.0f)
00222                         Spike = rand() % (int)(Effect->beBaseColors[nonDominant1]);
00223                 else
00224                         Spike = 0;
00225                 Effect->beCurrentColors[nonDominant1] -= Spike;
00226                 Effect->beCurrentColors[nonDominant2] -= Spike;
00227         }
00228         else
00229         {
00230                 Effect->beCurrentColors[nonDominant1] += Effect->beDecayRate;
00231                 Effect->beCurrentColors[nonDominant2] += Effect->beDecayRate;
00232                 if      (Effect->beCurrentColors[nonDominant1] > Effect->beBaseColors[nonDominant1])
00233                 {
00234                         Effect->beCurrentColors[nonDominant1] = Effect->beBaseColors[nonDominant1];
00235                         Effect->beCurrentColors[nonDominant2] = Effect->beBaseColors[nonDominant2];
00236                 }
00237         }
00238 
00239         Effect->beInitialized = 1;
00240         LowIndex = 0;
00241         HighIndex = Effect->beNumPoints;
00242         SubdivideStart = *start;
00243         SubdivideEnd   = *end;
00244 
00245         genLightning(Effect, LowIndex, HighIndex, &SubdivideStart, &SubdivideEnd);
00246 }
00247 
00248 //#define       LIGHTNINGALPHA  160.0f
00249 #define LIGHTNINGALPHA  220.0f
00250 
00251 void _Electric_BoltEffectRender(
00252         geWorld *                               World,
00253         _Electric_BoltEffect *  be,
00254         const geXForm3d *               XForm)
00255 {
00256         geVec3d                 perp;
00257         geVec3d                 temp;
00258         geVec3d                 in;
00259         GE_LVertex              verts[4];
00260         int                             i;
00261 
00262         geVec3d_Subtract(&be->beStart, &be->beEnd, &temp);
00263         geXForm3d_GetIn(XForm, &in);
00264 
00265         geVec3d_CrossProduct(&in, &temp, &perp);
00266         geVec3d_Normalize(&perp);
00267 
00268         geVec3d_Scale(&perp, be->beWidth / 2.0f, &perp);
00269 
00270         /*
00271                 We've got the perpendicular to the camera in the
00272                 rough direction of the electric bolt center.  Walk
00273                 the left and right sides, constructing verts, then
00274                 do the drawing.
00275         */
00276         for     (i = 0; i < be->beNumPoints - 1; i++)
00277         {
00278                 geVec3d temp;
00279 
00280                 geVec3d_Subtract(&be->beCenterPoints[i], &perp, &temp);
00281                 verts[0].X = temp.X;
00282                 verts[0].Y = temp.Y;
00283                 verts[0].Z = temp.Z;
00284                 verts[0].u = 0.0f;
00285                 verts[0].v = 0.0f;
00286                 verts[0].r = be->beCurrentColors[0];
00287                 verts[0].g = be->beCurrentColors[1];
00288                 verts[0].b = be->beCurrentColors[2];
00289                 verts[0].a = LIGHTNINGALPHA;
00290 
00291                 geVec3d_Subtract(&be->beCenterPoints[i + 1], &perp, &temp);
00292                 verts[1].X = temp.X;
00293                 verts[1].Y = temp.Y;
00294                 verts[1].Z = temp.Z;
00295                 verts[1].u = 0.0f;
00296                 verts[1].v = 1.0f;
00297                 verts[1].r = be->beCurrentColors[0];
00298                 verts[1].g = be->beCurrentColors[1];
00299                 verts[1].b = be->beCurrentColors[2];
00300                 verts[1].a = LIGHTNINGALPHA;
00301 
00302                 geVec3d_Add(&be->beCenterPoints[i + 1], &perp, &temp);
00303                 verts[2].X = temp.X;
00304                 verts[2].Y = temp.Y;
00305                 verts[2].Z = temp.Z;
00306                 verts[2].u = 1.0f;
00307                 verts[2].v = 1.0f;
00308                 verts[2].r = be->beCurrentColors[0];
00309                 verts[2].g = be->beCurrentColors[1];
00310                 verts[2].b = be->beCurrentColors[2];
00311                 verts[2].a = LIGHTNINGALPHA;
00312 
00313                 geVec3d_Add(&be->beCenterPoints[i], &perp, &temp);
00314                 verts[3].X = temp.X;
00315                 verts[3].Y = temp.Y;
00316                 verts[3].Z = temp.Z;
00317                 verts[3].u = 1.0f;
00318                 verts[3].v = 0.0f;
00319                 verts[3].r = be->beCurrentColors[0];
00320                 verts[3].g = be->beCurrentColors[1];
00321                 verts[3].b = be->beCurrentColors[2];
00322                 verts[3].a = LIGHTNINGALPHA;
00323 
00324                 geWorld_AddPolyOnce(World,
00325                                                         verts,
00326                                                         4,
00327                                                         NULL,
00328                                                         GE_GOURAUD_POLY,
00329                                                         GE_RENDER_DO_NOT_OCCLUDE_OTHERS,
00330                                                         1.0f);
00331 
00332         }
00333 }

Generated on Tue Sep 30 12:35:40 2003 for GTestAndEngine by doxygen 1.3.2