#ifndef jbt_blobtree_h #define jbt_blobtree_h #include <jgl/jgl.h> #include "attribute.h" #include "brackets.h" class jbt_blobtree { protected: jbt_blobtree() :cached(0) {} public: virtual ~jbt_blobtree() {} inline float bloomField( float, float, float ); jFlt intersect( const jRay&, jFlt = -1 ); virtual void beginQuery( const jVec3& ); inline const jVec3& queryPoint() const { return qp; } inline jFlt field(); inline jFlt bloomField(); inline const jNorm3& normal(); inline const jVec2& uv(); virtual void attribute( jbt_attribute* ) = 0; virtual void attributes( jbt_diffuse*, jbt_specular*, jbt_scalar*, jbt_scalar*, jbt_scalar* ) = 0; const jVec3& gradient(); const jBBox& bound() const { return bnd; } virtual void computeBound() = 0; virtual void seedPoints( jVec3list& ) const = 0; virtual bool spanCSG( const jVec3&, const jVec3& ) { return false; } virtual jgl_algebraic* expression( const jMat4& ) const = 0; enum Type { // primitives 0..99 jbtPoint=0, jbtLine, jbtVrLine, jbtDisk, jbtSquare, jbtPolyLine, jbtCircle, jbtPlane, // non-geometric nodes 100..199 jbtTransformation=100, jbtUVTransformation, jbtAttributeNode, jbtTwist, jbtTaper, jbtBend, jbtParameterize, jbtSeedPoint, jbtVecDisplace, jbtBumpMap, // combination 200..299 jbtBlend=200, jbtControlledBlend, jbtUnion, jbtIntersection, jbtDifference, // other >=300 jbtGeometric = 300, jbtNonGeometric }; static const jFlt L; virtual Type type() const = 0; virtual void bracket( const jRay& ray, jbt_brackets& ); virtual jNorm3 repulse() = 0; virtual void uv( jVec2&, jbt_blobtree*, const jMat4& ) = 0; static bool IsGeometric( const jbt_blobtree* ); static bool IsCompound( const jbt_blobtree* ); static bool IsPrimitive( const jbt_blobtree* ); virtual void name( char* ) const; static const char* Name( const jbt_blobtree* ); static void Write( const jbt_blobtree*, ostream&, int = 0 ); static void Write( const jbt_blobtree*, FILE*, int = 0 ); static jMat4 GetTransform( const jbt_blobtree* ); class lineeqn : public j1DImplicit { public: lineeqn( jbt_blobtree* _bt, const jRay& _ray ) : bt(_bt), ray(_ray) {} jFlt f( jFlt ); jFlt df( jFlt ); private: jbt_blobtree* bt; const jRay& ray; }; class sfceqn : public j2DImplicit { public: sfceqn( jbt_blobtree* _bt, const jVec3& _p, const jBasis& _B ) : bt(_bt), B(_B), p(_p) {} jFlt f( jFlt, jFlt ); private: jbt_blobtree* bt; jVec3 p; jBasis B; }; protected: jVec3 qp; virtual void field( jFlt& ) = 0; virtual void normal( jNorm3& ) = 0; jVec3 mapToSurface( const jVec3&, jbt_blobtree*, const jMat4& ); jBBox bnd; private: bool checkRoot( j1DImplicit*, jFlt&, jFlt, jFlt ); jULng cached; bool on( jULng f ) const { return cached&f; } bool off( jULng f ) const { return !on(f); } void setOn( jULng f ) { cached |= f; } void setOff( jULng f ) { cached = cached&(~f); } static const jULng fField; static const jULng fNormal; static const jULng fGradient; static const jULng fUV; jFlt fv; // field value jNorm3 N; // normal vector jVec3 G; // gradient vector jVec2 uvc; // texture coordinate friend class jbt_cache; }; jFlt jbt_blobtree::field() { if(off(fField)) { field(fv); setOn(fField); } return fv; } float jbt_blobtree::bloomField( float x, float y, float z ) { beginQuery(jVec3(x,y,z)); return 1.0-2*field(); } jFlt jbt_blobtree::bloomField() { return 1.0-2*field(); } const jNorm3& jbt_blobtree::normal() { if(off(fNormal)) { normal(N); setOn(fNormal); } return N; } const jVec2& jbt_blobtree::uv() { if(off(fUV)) { uv(uvc,this,jMat4()); setOn(fUV); } return uvc; } #endif