- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Examples

# latticeNoise.cpp

    //-
    // ==========================================================================
    // Copyright 1995,2006,2008 Autodesk, Inc. All rights reserved.
    //
    // Use of this software is subject to the terms of the Autodesk
    // license agreement provided at the time of installation or download,
    // or which otherwise accompanies this software in either electronic
    // or hard copy form.
    // ==========================================================================
    //+

    //
    //  File: latticeNoise.cc
    //
    //  Description:
    //      plugin registration code
    //

    #include "latticeNoise.h"
    #include <maya/MFnPlugin.h>
    #include <maya/MString.h>
    #include <stdlib.h>

    MStatus initializePlugin( MObject obj )
    {
        MStatus   status;
        MFnPlugin plugin( obj, PLUGIN_COMPANY, "3.0", "Any");

        // Register latticeNoise node
        //
        status = plugin.registerNode( "latticeNoise", latticeNoiseNode::id,
                                             latticeNoiseNode::creator,
                                             latticeNoiseNode::initialize);
        if (!status) {
            status.perror("registerNode");
            return status;
        }

        // Register latticeNoise command
        //
        status = plugin.registerCommand( "latticeNoise", latticeNoiseCmd::creator );
        if (!status) {
            plugin.deregisterNode( latticeNoiseNode::id );
            status.perror("registerCommand");
            return status;
        }

        return status;
    }

    MStatus uninitializePlugin( MObject obj)
    {
        MStatus   status;
        MFnPlugin plugin( obj );

        // Deregister latticeNoise node
        //
        status = plugin.deregisterNode( latticeNoiseNode::id );
        if (!status) {
            status.perror("registerNode");
            return status;
        }

        // Register latticeNoise command
        //
        status = plugin.deregisterCommand( "latticeNoise" );
        if (!status) {
            status.perror("deregisterCommand");
            return status;
        }

        return status;
    }

    //
    //  Class: noise
    //
    //  Description:
    //      The noise class is used for generating pseudo-random continuous noise.
    //      The noise values generated are always between 0 and 1.
    //
    //      The technique used is a simple lattice noise algorithm based upon one
    //      by Ken Perlin.  This particular implementation is adapted from
    //      Darwyn Peachey's (Texturing and Modeling: a Procedural Approach, S. Ebert
    //      Editor, 1994).
    //
    #include <stdlib.h>
    #include <math.h>

    const int kTableMask = TABLE_SIZE - 1;

    //                       PUBLIC                             //

    float noise::atValue( float x )
    //
    //  Description:
    //      Get the noise value at the given point in 1-space.
    //
    //  Arguments:
    //      x - the point at which to calculate the noise
    //
    //  Return Value:
    //      the noise value at the point
    //
    {
        int ix;
        float fx;

        if ( !isInitialized ) {
            initTable( 23479015 );
            isInitialized = 1;
        }

        ix = (int)floorf( x );
        fx = x - (float)ix;

        return spline( fx, value( ix - 1 ),
                           value( ix ),
                           value( ix + 1 ),
                           value( ix + 2 ) );
    }

    float noise::atPoint( float x, float y, float z )
    //
    //  Description:
    //      Get the noise value at the given point in 3-space.
    //
    //  Arguments:
    //      x - x component of point
    //      y - x component of point
    //      z - x component of point
    //
    //  Return Value:
    //      the noise value at the point
    //
    {
        int ix, iy, iz;
        int i, j, k;
        float fx, fy, fz;
        float xknots[4], yknots[4], zknots[4];

        if ( !isInitialized ) {
            initTable( 23479015 );
        }

        ix = (int)floorf( x );
        fx = x - (float)ix;

        iy = (int)floorf( y );
        fy = y - (float)iy;

        iz = (int)floorf( z );
        fz = z - (float)iz;

        for ( k = -1; k <= 2; k++ ) {
            for ( j = -1; j <= 2; j++ ) {
                for ( i = -1; i <= 2 ; i++ ) {
                    xknots[i+1] = value( ix + i, iy + j, iz + k );
                }
                yknots[j+1] = spline( fx, xknots[0], xknots[1], xknots[2], xknots[3] );
            }
            zknots[k+1] = spline( fy, yknots[0], yknots[1], yknots[2], yknots[3] );
        }

        float val = spline( fz, zknots[0], zknots[1], zknots[2], zknots[3] );

        return val;
    }

    pnt noise::atPointAndTime( float x, float y, float z, float t )
    //
    //  Description:
    //      Get three noise values at the given point in 4-space.  This is actually
    //      a reasonably expensive operation.  It requires 255 simple spline
    //      interpolations.  However, the noise function is continuous.
    //
    //  Arguments:
    //      x - x component of point
    //      y - x component of point
    //      z - x component of point
    //      t - t component of point (time component)
    //
    //  Return Value:
    //      the noise value at the point
    //
    {
        pnt ret;

        int ix, iy, iz, it;
        int i, j, k, l;
        float fx, fy, fz, ft;
        float xknots[3][4], yknots[3][4], zknots[3][4], tknots[3][4];

        if ( !isInitialized ) {
            initTable( 23479015 );
        }

        ix = (int)floorf( x );
        fx = x - (float)ix;

        iy = (int)floorf( y );
        fy = y - (float)iy;

        iz = (int)floorf( z );
        fz = z - (float)iz;

        it = (int)floorf( t);
        ft = t - (float)it;

        for ( l = -1; l <= 2; l++ ) {
            for ( k = -1; k <= 2; k++ ) {
                for ( j = -1; j <= 2; j++ ) {
                    for ( i = -1; i <= 2 ; i++ ) {
                        xknots[0][i+1] = value( ix + i, iy + j, iz + k, it + l,
                                                valueTable1 );
                        xknots[1][i+1] = value( ix + i, iy + j, iz + k, it + l,
                                                valueTable2 );
                        xknots[2][i+1] = value( ix + i, iy + j, iz + k, it + l,
                                                valueTable3 );
                    }
                    yknots[0][j+1] = spline( fx, xknots[0][0], xknots[0][1],
                                             xknots[0][2], xknots[0][3] );
                    yknots[1][j+1] = spline( fx, xknots[1][0], xknots[1][1],
                                             xknots[1][2], xknots[1][3] );
                    yknots[2][j+1] = spline( fx, xknots[2][0], xknots[2][1],
                                             xknots[2][2], xknots[2][3] );
                }
                zknots[0][k+1] = spline( fy, yknots[0][0], yknots[0][1],
                                         yknots[0][2], yknots[0][3] );
                zknots[1][k+1] = spline( fy, yknots[1][0], yknots[1][1],
                                         yknots[1][2], yknots[1][3] );
                zknots[2][k+1] = spline( fy, yknots[2][0], yknots[2][1],
                                         yknots[2][2], yknots[2][3] );
            }
            tknots[0][l+1] = spline( fz, zknots[0][0], zknots[0][1],
                                     zknots[0][2], zknots[0][3] );
            tknots[1][l+1] = spline( fz, zknots[1][0], zknots[1][1],
                                     zknots[1][2], zknots[1][3] );
            tknots[2][l+1] = spline( fz, zknots[2][0], zknots[2][1],
                                     zknots[2][2], zknots[2][3] );
        }
        ret.x = spline( ft, tknots[0][0], tknots[0][1], tknots[0][2], tknots[0][3] );
        ret.y = spline( ft, tknots[1][0], tknots[1][1], tknots[1][2], tknots[1][3] );
        ret.z = spline( ft, tknots[2][0], tknots[2][1], tknots[2][2], tknots[2][3] );

        return ret;
    }

    void  noise::initTable( long seed )
    //
    //  Description:
    //      Initialize the table of random values with the given seed.
    //
    //  Arguments:
    //      seed - the new seed value
    //
    {
        srand48( seed );

        for ( int i = 0; i < TABLE_SIZE; i++ ) {
            valueTable1[i] = (float)drand48();
            valueTable2[i] = (float)drand48();
            valueTable3[i] = (float)drand48();
        }
        isInitialized = 1;
    }

    //                       PRIVATE                            //

    float noise::spline( float x, float knot0, float knot1, float knot2, float knot3 )
    //
    //  Description:
    //      This is a simple version of a Catmull-Rom spline interpolation.
    //
    //  Assumptions:
    //
    //      0 < x < 1
    //
    //
    {
        float c0, c1, c2, c3;

        // Evaluate span of cubic at x using Horner's rule
        //
        c3 = (-0.5F * knot0 ) + ( 1.5F * knot1 ) + (-1.5F * knot2 ) + ( 0.5F * knot3 );
        c2 = ( 1.0F * knot0 ) + (-2.5F * knot1 ) + ( 2.0F * knot2 ) + (-0.5F * knot3 );
        c1 = (-0.5F * knot0 ) + ( 0.0F * knot1 ) + ( 0.5F * knot2 ) + ( 0.0F * knot3 );
        c0 = ( 0.0F * knot0 ) + ( 1.0F * knot1 ) + ( 0.0F * knot2 ) + ( 0.0F * knot3 );

        return ( ( c3 * x + c2 ) * x + c1 ) * x + c0;;
    }

    int noise::isInitialized = 0;

    int noise::permtable[256] = {
        254,    91,     242,    186,    90,     204,    85,     133,    233,
        50,     187,    49,     182,    224,    144,    166,    7,      51,
        20,     179,    36,     203,    114,    156,    195,    40,     24,
        60,     162,    84,     126,    102,    63,     194,    220,    161,
        72,     94,     193,    229,    140,    57,     3,      189,    106,
        54,     164,    198,    199,    44,     245,    235,    100,    87,
        25,     41,     62,     111,    13,     70,     27,     82,     69,
        53,     66,     247,    124,    67,     163,    125,    155,    228,
        122,    19,     113,    143,    121,    9,      1,      241,    171,
        200,    83,     244,    185,    170,    141,    115,    190,    154,
        48,     32,     178,    127,    167,    56,     134,    15,     160,
        238,    64,     6,      11,     196,    232,    26,     89,     0,
        219,    112,    68,     30,     215,    227,    75,     132,    71,
        239,    251,    92,     14,     104,    231,    29,     180,    150,
        226,    191,    47,     73,     37,     183,    88,     105,    42,
        22,     2,      38,     5,      119,    74,     249,    184,    52,
        8,      55,     118,    255,    206,    173,    165,    78,     31,
        123,    98,     212,    80,     139,    61,     138,    77,     177,
        45,     137,    145,    28,     168,    128,    95,     223,    35,
        205,    76,     211,    175,    81,     33,     207,    21,     131,
        58,     152,    16,     240,    18,     96,     210,    109,    214,
        216,    202,    148,    34,     146,    117,    176,    93,     246,
        172,    97,     159,    197,    218,    65,     147,    253,    221,
        217,    79,     101,    142,    23,     149,    99,     39,     12,
        135,    110,    234,    108,    153,    129,    4,      169,    174,
        116,    243,    130,    107,    222,    10,     43,     188,    46,
        213,    252,    86,     157,    192,    236,    158,    120,    17,
        103,    248,    225,    230,    250,    208,    181,    151,    237,
        201,    59,     136,    209
    };

    float noise::valueTable1[256];
    float noise::valueTable2[256];
    float noise::valueTable3[256];