This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

| Hypercloud Texture Code Submitted by

A procedural hypertexture (4D) that synthesizes multiple levels of arbitrary located "puffs" to simulate clouds or another chaos of elements with slight modifications (e.g. the gravel,scratches,starfield,horns generatorfunctions of I-Tex). For animated clouds you can also modulate the input values by another hypertexture, e.g. 4D Perlin Noise, this makes it even more realistic. The texture can be shaded if you use the fx,fy and fz values as 3D Point and calculate the angle to the light source from it.

Download Associated File: hypercloud.h (7,702 bytes)

    //////////////////////////////////////////////////////////////////////////////
    //     File: hypercloud.h
    //  Created: 28.11.2001 in Delphi for I-Tex 2.2, converted to C++ 3.2.2002
    //   Author: Tobias Reichert
    //    Email: tobias_reichert@i-tex.de
    //  Summary: The class THyperCloudTexture is initialized
    //           with the Init(...) method that sets random seed and
    //           initializes the parameters and random value cache.
    //           double GetValue4D(x,y,z,time) returns a depth value [0..1).
    //           Animated this looks life boiling water ;-)
    //           Computation Expense : O(Octaves*Density*2^Dimension),
    //           nothing for realtime apps, but can be optimized a lot
    //////////////////////////////////////////////////////////////////////////////

    #include "math.hpp"
    #include "math.h"

    class THyperCloudTexture
          {
           int RSeed;           //Random Seed, use full range
           int Octaves;         //Detail, Proportional to Computation Expense, use 6+
           int Density;         //Number of Puffs per Gridcell, use [1..20]
           double SubScale;     //Resolution for Octave(n)=Subscale^n, use [1 .. 4]
           double Persistance;  //Valence for Octave(n)=
                                //Persistance^n/Sum(all Octave Valences)
                                //use [0 .. 1)
           double ReciPuffSize; //1/Size of Cloud Puffs, use [0.5 .. 1)
           double Amplify;      //Values can be very low, scale with this
           double Bias;         //Make also Brighter with this Value

           double ReciOctaveSum; //is 1/Sum(all Octave Valances), Initialized by Init()

           double FNoiseArray[1024]; //RandomPool of Doubles
           int INoiseArray[1024]; //RandomPool of Integers

           private:
            double __fastcall DirectRandom(int i);

           public:
            void __fastcall Init(int    pRSeed,
                                 int    pOctaves,
                                 int    pDensity,
                                 double pSubScale,
                                 double pPersistance,
                                 double pPuffSize,
                                 double pAmplify,
                                 double pBias);

            double __fastcall GetValue4D(double x,
                                         double y,
                                         double z,
                                         double t);
          };

    double __fastcall THyperCloudTexture::DirectRandom(int i)
    {
     return abs(((i +  i * ( 89603  +   i *46703) ) * 114269) % 9995057 )
                * (double)1.000494544453323e-7;
    }

    void __fastcall THyperCloudTexture::Init(int    pRSeed,
                                             int    pOctaves,
                                             int    pDensity,
                                             double pSubScale,
                                             double pPersistance,
                                             double pPuffSize,
                                             double pAmplify,
                                             double pBias)
     //Example :  THyperCloudTexture *Clouds;
     //           Clouds=new(THyperCloudTexture);
     //           Clouds->Init(123,6,20,2,0.6,0.8,4,0.1);

    {
     //Copy Parameters to Internal Variables

     RSeed = pRSeed;
     Octaves = pOctaves;
     Density = pDensity;
     SubScale = pSubScale;
     Persistance = pPersistance;

     //Puffs with Size=0 would not be very useful (and cause DbZ)
     if (pPuffSize>0) { ReciPuffSize = sqrt(1/pPuffSize); }
                      else
                      { ReciPuffSize = 10; }

     Amplify = pAmplify;
     Bias = pBias;

     //Compute 1/Sum(persistance^n,n=0..octaves-1);

     if (Octaves==0) {Octaves=1;} //Just for the case ...

     if (Persistance==1)
              { ReciOctaveSum = 1/Octaves; }
              else
              { ReciOctaveSum = (Persistance-1) / (IntPower(Persistance,Octaves) - 1) ; }

     //Init Cached Random Arrays

     for (int i=0; i<1024; i++)
     {
      FNoiseArray[i] = DirectRandom(i*101+RSeed);
      INoiseArray[i] = (int)(33111*DirectRandom(i*91+RSeed));
     }
    }

    double __fastcall THyperCloudTexture::GetValue4D(double x,
                                                     double y,
                                                     double z,
                                                     double t)
    {
     int i,d; //Some Working Variables
     int tx,ty,tz,tt; //Scan loop Variables
     int nd; //Octave "ANDing" Argument = 2^n-1

     double c=0; //Return Value
     double b;
     double p=1; //Persistance

     int    intx,inty,intz,intt;
     int    offx,offy,offz,offt;
     double fracx,fracy,fracz,fract;
     double fx,fy,fz,ft;
     int inoff;
     double SqrDist;
     double PuffDens;
     double ReciSize;

     int cachex,cachey,cachez,cachet;
     int r;

     for (i=0;i<Octaves;i++) //Add Octaves
     {
      nd=(256<<i)-1;

      inoff = i * 44111 + RSeed; //Every Octave uses modified RSeed

      intx  = (int)x; //round down to Int of x,y,z,t
      inty  = (int)y;
      intz  = (int)z;
      intt  = (int)t;

      fracx = x-(double)intx; //fraction [0..1) value of x,y,z,t
      fracy = y-(double)inty;
      fracz = z-(double)intz;
      fract = t-(double)intt;

      //Determine Cells to be checked
      (fracx<0.5) ? (offx=-1) : (offx=0);
      (fracy<0.5) ? (offy=-1) : (offy=0);
      (fracz<0.5) ? (offz=-1) : (offz=0);
      (fract<0.5) ? (offt=-1) : (offt=0);

      //Initialize Octave-Value b
      b=0;

      for (d=0;d<Density;d++)
      {

       for (tt=offt;tt<=offt+1;tt++) //Scan for Overlapping Cells in dim-(t)ime
       {
        cachet = ((intt+tt) & nd);

        for (tz=offz;tz<=offz+1;tz++) //Scan for Overlapping Cells in dim-z
        {
         cachez = ((intz+tz) & nd);

         for (ty=offy;ty<=offy+1;ty++) //Scan for Overlapping Cells in dim-y
         {
          cachey = ((inty+ty) & nd);

          for (tx=offx;tx<=offx+1;tx++) //Scan for Overlapping Cells in dim-x
          {
           cachex = ((intx+tx) & nd);

           //Compute x-coordinate of element d
           r = cachex*33001 + cachey*49937 + cachez*53441 + cachet*21839 + inoff;
           fx = (double)tx+FNoiseArray[(INoiseArray[r & 1023] + r * 52223) & 1023]-fracx;

           //Compute y-coordinate of element d
           r = cachex*49937 + cachey*53441 + cachez*21839 + cachet*33001 + inoff;
           fy = (double)ty+FNoiseArray[(INoiseArray[r & 1023] + r * 21839) & 1023]-fracy;

           //Compute t-coordinate of element d
           r = cachex*53441 + cachey*21839 + cachez*33001 + cachet*49937 + inoff;
           fz = (double)tz+FNoiseArray[(INoiseArray[r & 1023] + r * 49937) & 1023]-fracz;

           //Compute t-coordinate of element d
           r = cachex*21839 + cachey*33001 + cachez*49937 + cachet*53441 + inoff;
           ft = (double)tt+FNoiseArray[(INoiseArray[r & 1023] + r * 53441) & 1023]-fract;

           //Compute 1/Size of element d
           r = cachex*33001 + cachey*49937 + cachez*53441 + cachet*21839 + inoff;
           ReciSize = ((2+FNoiseArray[(INoiseArray[r & 1023] + r * 52223) & 1023])*ReciPuffSize);

           //Compute brightness of element d
           r = cachex*33001 + cachey*21839 + cachez*53441 + cachet*49937 + inoff;
           PuffDens = 0.1+0.9*(FNoiseArray[(INoiseArray[r & 1023] + r * 52223) & 1023]);

           //Compute 1-(Pixel-Puff-Distance)^2 , Distance = Sum((Dimension-Distance)^2)
           SqrDist = PuffDens * (1-(fx*fx + fy*fy + fz*fz + ft*ft)*ReciSize*ReciSize);
           //If distance is lower (1-distance greater) than beforce, remember it
           if (SqrDist>b) { b=SqrDist; }

          } //End tx-loop
         } //End ty-loop
        } //End tz-loop
       } //End tt-loop

       //Change Random for each Element
       inoff += 101;

      } //End d-loop

      //Add Result of the Octave * Persistance
      c += sqrt(b)*p;

      //Higher Octaves are scaled with the SubScale Parameter
      x*=SubScale;
      y*=SubScale;
      z*=SubScale;
      t*=SubScale;

      //Compute Next Persistance
      p*=Persistance;
     }

     //Scale and Transform Result and Return Value
     return  1-exp(-c*Amplify * ReciOctaveSum - Bias);
    }

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.