//- // ========================================================================== // Copyright (C) 1995 - 2006 Autodesk, Inc. and/or its licensors. All // rights reserved. // // The coded instructions, statements, computer programs, and/or related // material (collectively the "Data") in these files contain unpublished // information proprietary to Autodesk, Inc. ("Autodesk") and/or its // licensors, which is protected by U.S. and Canadian federal copyright // law and by international treaties. // // The Data is provided for use exclusively by You. You have the right // to use, modify, and incorporate this Data into other products for // purposes authorized by the Autodesk software license agreement, // without fee. // // The copyright notices in the Software and this entire statement, // including the above license grant, this restriction and the // following disclaimer, must be included in all copies of the // Software, in whole or in part, and all derivative works of // the Software, unless such copies or derivative works are solely // in the form of machine-executable object code generated by a // source language processor. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. // AUTODESK DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED // WARRANTIES INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF // NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR // PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE, OR // TRADE PRACTICE. IN NO EVENT WILL AUTODESK AND/OR ITS LICENSORS // BE LIABLE FOR ANY LOST REVENUES, DATA, OR PROFITS, OR SPECIAL, // DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES, EVEN IF AUTODESK // AND/OR ITS LICENSORS HAS BEEN ADVISED OF THE POSSIBILITY // OR PROBABILITY OF SUCH DAMAGES. // // ========================================================================== //+ #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Local functions float Noise(float, float, float); void Noise_init(); static float Omega(int i, int j, int k, float t[3]); static float omega(float); static double turbulence(double u,double v,double w,int octaves); #define PI 3.14159265358979323846 #ifdef FLOOR #undef FLOOR #endif #define FLOOR(x) ((int)floorf(x)) #define TABLELEN 512 #define TLD2 256 // TABLELEN // Local variables static int Phi[TABLELEN]; static char fPhi[TABLELEN]; static float G[TABLELEN][3]; class Lava3D : public MPxNode { public: Lava3D(); virtual ~Lava3D(); virtual MStatus compute( const MPlug&, MDataBlock& ); virtual void postConstructor(); static void * creator(); static MStatus initialize(); // Id tag for use with binary file format static MTypeId id; private: // Input attributes static MObject aColorBase; static MObject aColorFlame; static MObject aDeform; static MObject aWarp; static MObject aSpeed; static MObject aTurbulence; static MObject aPower; static MObject aFrame; static MObject aPointWorld; static MObject aPlaceMat; // Output attributes static MObject aOutColor; static MObject aOutAlpha; }; // Static data MTypeId Lava3D::id(0x81015); // Attributes MObject Lava3D::aColorBase; MObject Lava3D::aColorFlame; MObject Lava3D::aDeform; MObject Lava3D::aWarp; MObject Lava3D::aSpeed; MObject Lava3D::aTurbulence; MObject Lava3D::aPower; MObject Lava3D::aFrame; MObject Lava3D::aPointWorld; MObject Lava3D::aPlaceMat; MObject Lava3D::aOutColor; MObject Lava3D::aOutAlpha; #define MAKE_INPUT(attr) \ CHECK_MSTATUS ( attr.setKeyable(true) ); \ CHECK_MSTATUS ( attr.setStorable(true) ); \ CHECK_MSTATUS ( attr.setReadable(true) ) ; \ CHECK_MSTATUS ( attr.setWritable(true) ); #define MAKE_OUTPUT(attr) \ CHECK_MSTATUS ( attr.setKeyable(false) ); \ CHECK_MSTATUS ( attr.setStorable(false) ) ; \ CHECK_MSTATUS ( attr.setReadable(true) ); \ CHECK_MSTATUS ( attr.setWritable(false) ); // // DESCRIPTION: /////////////////////////////////////////////////////// void Lava3D::postConstructor() { setMPSafe(true); } // // DESCRIPTION: /////////////////////////////////////////////////////// Lava3D::Lava3D() { } // // DESCRIPTION: /////////////////////////////////////////////////////// Lava3D::~Lava3D() { } // // DESCRIPTION: /////////////////////////////////////////////////////// void * Lava3D::creator() { return new Lava3D(); } // // DESCRIPTION: /////////////////////////////////////////////////////// MStatus Lava3D::initialize() { MFnMatrixAttribute mAttr; MFnNumericAttribute nAttr; // Input attributes aColorBase = nAttr.createColor("ColorBase", "cb"); MAKE_INPUT(nAttr); aColorFlame = nAttr.createColor("ColorFlame", "cf"); MAKE_INPUT(nAttr); CHECK_MSTATUS ( nAttr.setDefault(1., 1., 1.) ); aDeform = nAttr.create( "Deformation", "d", MFnNumericData::kLong); MAKE_INPUT(nAttr); CHECK_MSTATUS ( nAttr.setDefault(1) ); CHECK_MSTATUS (nAttr.setMin(1) ); CHECK_MSTATUS ( nAttr.setMax(10) ); aWarp = nAttr.create( "Warp", "w", MFnNumericData::kFloat); MAKE_INPUT(nAttr); CHECK_MSTATUS ( nAttr.setDefault(0.1f) ); CHECK_MSTATUS ( nAttr.setMin(0.0f) ); CHECK_MSTATUS ( nAttr.setMax(10.0f) ); aSpeed = nAttr.create( "Speed", "ws", MFnNumericData::kFloat); MAKE_INPUT(nAttr); CHECK_MSTATUS ( nAttr.setDefault(0.1f) ); CHECK_MSTATUS (nAttr.setMin(0.0f) ); CHECK_MSTATUS (nAttr.setMax(1.0f) ); aTurbulence = nAttr.create( "Turbulence", "t", MFnNumericData::kLong); MAKE_INPUT(nAttr); CHECK_MSTATUS ( nAttr.setDefault(2) ); CHECK_MSTATUS ( nAttr.setMin(1) ); CHECK_MSTATUS ( nAttr.setMax(10) ); aPower = nAttr.create( "Power", "pow", MFnNumericData::kFloat); MAKE_INPUT(nAttr); CHECK_MSTATUS ( nAttr.setDefault(1.0f) ); CHECK_MSTATUS ( nAttr.setMin(0.0f) ); CHECK_MSTATUS ( nAttr.setMax(100.0f) ); aFrame = nAttr.create( "Frame", "f", MFnNumericData::kFloat); MAKE_INPUT(nAttr); CHECK_MSTATUS ( nAttr.setDefault(1.0f) ); CHECK_MSTATUS ( nAttr.setMin(0.0f) ); CHECK_MSTATUS ( nAttr.setMax(1000.0f) ); aPlaceMat = mAttr.create("placementMatrix", "pm", MFnMatrixAttribute::kFloat); MAKE_INPUT(mAttr); // Implicit shading network attributes aPointWorld = nAttr.createPoint("pointWorld", "pw"); MAKE_INPUT(nAttr); CHECK_MSTATUS ( nAttr.setHidden(true) ); // Create output attributes aOutColor = nAttr.createColor("outColor", "oc"); MAKE_OUTPUT(nAttr); aOutAlpha = nAttr.create( "outAlpha", "oa", MFnNumericData::kFloat); MAKE_OUTPUT(nAttr); // Add attributes to the node database. CHECK_MSTATUS ( addAttribute(aColorBase) ); CHECK_MSTATUS ( addAttribute(aColorFlame) ); CHECK_MSTATUS ( addAttribute(aDeform) ); CHECK_MSTATUS ( addAttribute(aWarp) ); CHECK_MSTATUS ( addAttribute(aSpeed) ); CHECK_MSTATUS ( addAttribute(aTurbulence) ); CHECK_MSTATUS ( addAttribute(aPower) ); CHECK_MSTATUS ( addAttribute(aFrame) ); CHECK_MSTATUS ( addAttribute(aPointWorld) ); CHECK_MSTATUS ( addAttribute(aPlaceMat) ); CHECK_MSTATUS ( addAttribute(aOutAlpha) ); CHECK_MSTATUS ( addAttribute(aOutColor) ); // All input affect the output color and alpha CHECK_MSTATUS ( attributeAffects( aColorBase, aOutColor) ); CHECK_MSTATUS ( attributeAffects( aColorFlame, aOutColor) ); CHECK_MSTATUS ( attributeAffects( aDeform, aOutColor) ); CHECK_MSTATUS ( attributeAffects( aWarp, aOutColor) ); CHECK_MSTATUS ( attributeAffects( aSpeed, aOutColor) ); CHECK_MSTATUS ( attributeAffects( aTurbulence, aOutColor) ); CHECK_MSTATUS ( attributeAffects( aPower, aOutColor) ); CHECK_MSTATUS ( attributeAffects( aFrame, aOutColor) ); CHECK_MSTATUS ( attributeAffects( aPointWorld, aOutColor) ); CHECK_MSTATUS ( attributeAffects( aPlaceMat, aOutColor) ); CHECK_MSTATUS ( attributeAffects (aColorBase, aOutAlpha) ); CHECK_MSTATUS ( attributeAffects (aColorFlame, aOutAlpha) ); CHECK_MSTATUS ( attributeAffects (aDeform, aOutAlpha) ); CHECK_MSTATUS ( attributeAffects (aWarp, aOutAlpha) ); CHECK_MSTATUS ( attributeAffects (aSpeed, aOutAlpha) ); CHECK_MSTATUS ( attributeAffects (aTurbulence, aOutAlpha) ); CHECK_MSTATUS ( attributeAffects (aPower, aOutAlpha) ); CHECK_MSTATUS ( attributeAffects (aFrame, aOutAlpha) ); CHECK_MSTATUS ( attributeAffects (aPointWorld, aOutAlpha) ); CHECK_MSTATUS ( attributeAffects (aPlaceMat, aOutAlpha) ); return MS::kSuccess; } /////////////////////////////////////////////////////// // DESCRIPTION: // This function gets called by Maya to evaluate the texture. // /////////////////////////////////////////////////////// MStatus Lava3D::compute(const MPlug& plug, MDataBlock& block) { if ( (plug != aOutColor) && (plug.parent() != aOutColor) && (plug != aOutAlpha) ) return MS::kUnknownParameter; const float3& worldPos = block.inputValue(aPointWorld).asFloat3(); const MFloatMatrix& m = block.inputValue(aPlaceMat).asFloatMatrix(); const MFloatVector& cBase = block.inputValue(aColorBase).asFloatVector(); const MFloatVector& cFlame =block.inputValue(aColorFlame).asFloatVector(); const int deform = block.inputValue( aDeform ).asLong(); const float warp = block.inputValue( aWarp ).asFloat(); const float speed = block.inputValue( aSpeed ).asFloat(); const int turbValue = block.inputValue( aTurbulence ).asLong(); const float power = block.inputValue( aPower ).asFloat(); const float frame = block.inputValue( aFrame ).asFloat(); MFloatPoint q(worldPos[0], worldPos[1], worldPos[2]); q *= m; // Convert into solid space float u, v, w; u = q.x; v = q.y; w = q.z; float dist = speed * frame; float au, av, aw; au = u + dist; av = v + dist; aw = w + dist; // Calculate 3 noise values float ascale = (float) turbulence( au, av, aw,(int)deform); float bscale = (float) turbulence( au,-av, aw,(int)deform); float cscale = (float) turbulence(-au, av,-aw,(int)deform); float dscale = warp; // Add this noise as a vector to the texture coordinates // (since we are only calculating one value, the // displacement will be alont the 1 1 1 vector ... this // displacement generates the "flicker" movement as the // value moves around the texture coordinate u += ascale * dscale; v += bscale * dscale; w += cscale * dscale; // Calculate a turbulence value for this point float scalar = (float) (turbulence(u,v,w,(int)turbValue) + 0.5); // convert scalar into a point on the color curve if (power != 1) scalar = powf (scalar, power); MDataHandle outHandle = block.outputValue( aOutColor ); MFloatVector & outColor = outHandle.asFloatVector(); outColor = ((cFlame-cBase)*scalar) + cBase; outHandle.setClean(); outHandle = block.outputValue(aOutAlpha); outHandle.asFloat() = scalar; outHandle.setClean(); return MS::kSuccess; } ////////////////////////////////////////////////////////////////// MStatus initializePlugin( MObject obj ) { const MString UserClassify( "texture/3d" ); MFnPlugin plugin( obj, PLUGIN_COMPANY, "4.5", "Any" ); CHECK_MSTATUS ( plugin.registerNode( "lava", Lava3D::id, Lava3D::creator, Lava3D::initialize, MPxNode::kDependNode, &UserClassify) ); Noise_init(); return MS::kSuccess; } // DESCRIPTION: /////////////////////////////////////////////////////// MStatus uninitializePlugin( MObject obj ) { MFnPlugin plugin( obj ); CHECK_MSTATUS ( plugin.deregisterNode( Lava3D::id ) ); return MS::kSuccess; } // // REFERENCES: // Perlin, K. An Image Synthesizer, Computer Graphics, // Vol. 19, No. 3, July 1985. // // Perlin, K., Hoffert, E.M., Hypertexture, Computer Graphics, // Vol. 23, No. 3, July 1989. // float Noise(float u, float v, float w) { int i; int j; int k; int ul; int vl; int wl; float ans; float t[3]; ans = 0.0; ul = FLOOR(u); vl = FLOOR(v); wl = FLOOR(w); for(i = ul + 1; i >= ul; i--) { t[0] = u - i; for(j = vl + 1; j >= vl; j--) { t[1] = v - j; for(k = wl + 1; k >= wl; k--) { t[2] = w - k; ans += Omega(i, j, k, t); } } } return ans; } static float Omega(int i, int j, int k, float t[3]) { int ct; ct = Phi[((i + Phi[((j + Phi[(k%TLD2)+TLD2]) % TLD2) + TLD2]) % TLD2) + TLD2]; return omega(t[0]) * omega(t[1]) * omega(t[2]) * ( G[ct][0]*t[0] + G[ct][1]*t[1] + G[ct][2]*t[2] ); } static float omega(float t) { t = fabsf(t); return (t * (t * (t * (float)2.0 - (float)3.0))) + (float)1.0; } void Noise_init() { int i; float u, v, w, s, len; static int first_time = 1; if (first_time) first_time = 0; else return; (void)srand48(0l); for(i = 0; i < TABLELEN; i++) fPhi[i] = 0; for(i = 0; i < TABLELEN; i++) { Phi[i] = lrand48() % TABLELEN; if (fPhi[Phi[i]]) i--; else fPhi[Phi[i]] = 1; } for(i = 0; i < TABLELEN; i++) { u = (float) (2.0 * drand48() - 1.0); v = (float) (2.0 * drand48() - 1.0); w = (float) (2.0 * drand48() - 1.0); if((s = u*u + v*v + w*w) > 1.0) { i--; continue; } else if (s == 0.0) { i--; continue; } len = 1.0f / sqrtf(s); G[i][0] = u * len; G[i][1] = v * len; G[i][2] = w * len; } } static double turbulence(double u,double v,double w,int octaves) { double s,t; s = 1.0; t = 0.0; while (octaves--) { t += Noise((float)u, (float)v, (float)w)*s; s *= 0.5; u*=2.0; v*=2.0; w*=2.0; } return t; }