// // Vrml 97 library // Copyright (C) 1998 Chris Morley // // %W% %G% // VrmlField.cpp // The VrmlField class is the base field class. // #include "config.h" #include "VrmlField.h" #include // memcpy #include "MathUtils.h" #if defined AW_NEW_IOSTREAMS # include #else # include #endif VrmlField::VrmlField() {} // Even though it is a pure virtual function, the destructor needs a definition // since each destructor in the inheritance hierarchy is called when a derived // object is destroyed. VrmlField::~VrmlField() {} VrmlField::VrmlFieldType VrmlField::fieldType() const { return NO_FIELD; } // A static method to convert a type name to an ID. VrmlField::VrmlFieldType VrmlField::fieldType(const char *type) { if (strcmp(type, "SFBool") == 0) return SFBOOL; if (strcmp(type, "SFColor") == 0) return SFCOLOR; if (strcmp(type, "SFFloat") == 0) return SFFLOAT; if (strcmp(type, "SFImage") == 0) return SFIMAGE; if (strcmp(type, "SFInt32") == 0) return SFINT32; if (strcmp(type, "SFNode") == 0) return SFNODE; if (strcmp(type, "SFRotation") == 0) return SFROTATION; if (strcmp(type, "SFString") == 0) return SFSTRING; if (strcmp(type, "SFTime") == 0) return SFTIME; if (strcmp(type, "SFVec2f") == 0) return SFVEC2F; if (strcmp(type, "SFVec3f") == 0) return SFVEC3F; if (strcmp(type, "MFColor") == 0) return MFCOLOR; if (strcmp(type, "MFFloat") == 0) return MFFLOAT; if (strcmp(type, "MFInt32") == 0) return MFINT32; if (strcmp(type, "MFNode") == 0) return MFNODE; if (strcmp(type, "MFRotation") == 0) return MFROTATION; if (strcmp(type, "MFString") == 0) return MFSTRING; if (strcmp(type, "MFVec2f") == 0) return MFVEC2F; if (strcmp(type, "MFVec3f") == 0) return MFVEC3F; return NO_FIELD; } static char *ftn[] = { "SFBool", "SFColor", "SFFloat", "SFInt32", "SFRotation", "SFTime", "SFVec2f", "SFVec3f", "SFImage", "SFString", "MFColor", "MFFloat", "MFInt32", "MFRotation", "MFString", "MFVec2f", "MFVec3f", "SFNode", "MFNode" }; // Return the type name of a field const char* VrmlField::fieldTypeName() const { int ft = (int) this->fieldType(); if (ft > 0 && ft <= (int) VrmlField::MFNODE) return ftn[ft-1]; return ""; } // Printing methods ostream& operator<<(ostream& os, const VrmlField& f) { return f.print(os); } // SFBool #include "VrmlSFBool.h" VrmlSFBool::VrmlSFBool(bool value) : d_value(value) {} ostream& VrmlSFBool::print(ostream& os) const { return (os << (d_value ? "TRUE" : "FALSE")); } VrmlField *VrmlSFBool::clone() const { return new VrmlSFBool(d_value); } VrmlField::VrmlFieldType VrmlSFBool::fieldType() const { return SFBOOL; } // SFColor #include "VrmlSFColor.h" VrmlSFColor::VrmlSFColor(float r, float g, float b) { d_rgb[0] = r; d_rgb[1] = g; d_rgb[2] = b; } ostream& VrmlSFColor::print(ostream& os) const { return (os << d_rgb[0] << ' ' << d_rgb[1] << ' ' << d_rgb[2]); } VrmlField *VrmlSFColor::clone() const { return new VrmlSFColor(d_rgb[0],d_rgb[1],d_rgb[2]); } VrmlField::VrmlFieldType VrmlSFColor::fieldType() const { return SFCOLOR; } // Conversion functions between RGB each in [0,1] and HSV with // h in [0,360), s,v in [0,1]. From Foley, van Dam p615-616. void VrmlSFColor::HSVtoRGB( float h, float s, float v, float &r, float &g, float &b) { if ( s == 0.0 ) { r = g = b = v; } else { if ( h >= 360.0 ) h -= 360.0; h /= 60.0; float i = floor(h); float f = h - i; float p = v * ( 1.0f - s ); float q = v * ( 1.0f - s * f ); float t = v * ( 1.0f - s * (1.0f - f) ); switch ((int) i) { default: case 0: r = v; g = t; b = p; break; case 1: r = q; g = v; b = p; break; case 2: r = p; g = v; b = t; break; case 3: r = p; g = q; b = v; break; case 4: r = t; g = p; b = v; break; case 5: r = v; g = p; b = q; break; } } } void VrmlSFColor::RGBtoHSV( float r, float g, float b, float &h, float &s, float &v) { float maxrgb = (r > g) ? ((r > b) ? r : b) : ((g > b) ? g : b); float minrgb = (r < g) ? ((r < b) ? r : b) : ((g < b) ? g : b); h = 0.0; v = maxrgb; if ( maxrgb > 0.0 ) s = (maxrgb - minrgb) / maxrgb; else s = 0.0; if ( s != 0.0 ) { float rc = (maxrgb - r) / (maxrgb - minrgb); float gc = (maxrgb - g) / (maxrgb - minrgb); float bc = (maxrgb - b) / (maxrgb - minrgb); if ( r == maxrgb ) h = bc - gc; else if ( g == maxrgb ) h = 2 + rc - bc; else if ( b == maxrgb ) h = 4 + gc - rc; h *= 60.0; if ( h < 0.0 ) h += 360.0; } } void VrmlSFColor::setHSV(float h, float s, float v) { HSVtoRGB( h, s, v, d_rgb[0], d_rgb[1], d_rgb[2] ); } void VrmlSFColor::getHSV(float& h, float& s, float& v) { RGBtoHSV( d_rgb[0], d_rgb[1], d_rgb[2], h, s, v ); } // SFFloat #include "VrmlSFFloat.h" VrmlSFFloat::VrmlSFFloat(float value) : d_value(value) {} ostream& VrmlSFFloat::print(ostream& os) const { return (os << d_value); } VrmlField *VrmlSFFloat::clone() const { return new VrmlSFFloat(d_value); } VrmlField::VrmlFieldType VrmlSFFloat::fieldType() const { return SFFLOAT; } // SFImage #include "VrmlSFImage.h" VrmlSFImage::VrmlSFImage(int w, int h, int nc, unsigned char *pixels) : d_w(w), d_h(h), d_nc(nc), d_pixels(pixels) { } VrmlSFImage::VrmlSFImage(const VrmlSFImage& sfi) : d_w(sfi.d_w), d_h(sfi.d_h), d_nc(sfi.d_nc), d_pixels(0) { int nbytes = d_w * d_h * d_nc; if ((d_pixels = new unsigned char[nbytes]) != 0) { memcpy(d_pixels, sfi.d_pixels, nbytes); } } VrmlSFImage::~VrmlSFImage() { delete [] d_pixels; } VrmlSFImage& VrmlSFImage::operator=(const VrmlSFImage& rhs) { if (this == &rhs) return *this; if (d_pixels) delete [] d_pixels; d_w = d_h = d_nc = 0; int nbytes = rhs.d_w * rhs.d_h * rhs.d_nc; if ((d_pixels = new unsigned char[nbytes]) != 0) { d_w = rhs.d_w; d_h = rhs.d_h; d_nc = rhs.d_nc; memcpy(d_pixels, rhs.d_pixels, nbytes); } return *this; } ostream& VrmlSFImage::print(ostream& os) const { os << d_w << " " << d_h << " " << d_nc; int np = d_w*d_h; unsigned char *p = d_pixels; for (int i=0; ireference(); } VrmlSFNode::VrmlSFNode(const VrmlSFNode &n) : d_value(n.d_value) { if (d_value) d_value->reference(); } VrmlSFNode::~VrmlSFNode() { if (d_value) d_value->dereference(); } VrmlSFNode& VrmlSFNode::operator=(const VrmlSFNode& rhs) { if (this == &rhs) return *this; if (d_value) d_value->dereference(); d_value = rhs.d_value; if (d_value) d_value->reference(); return *this; } ostream& VrmlSFNode::print(ostream& os) const { return os << *(d_value) << endl; } VrmlField *VrmlSFNode::clone() const { return new VrmlSFNode(d_value); } VrmlField::VrmlFieldType VrmlSFNode::fieldType() const { return SFNODE; } void VrmlSFNode::set(VrmlNode *value) { if (d_value) d_value->dereference(); if ((d_value = value) != 0) d_value->reference(); } // SFRotation #include "VrmlSFRotation.h" VrmlSFRotation::VrmlSFRotation(float x, float y, float z, float r) { d_x[0] = x; d_x[1] = y; d_x[2] = z; d_x[3] = r; } ostream& VrmlSFRotation::print(ostream& os) const { return (os <x() + d_x[1] * v->y(); } double VrmlSFVec2f::length() { return sqrt(d_x[0] * d_x[0] + d_x[1] * d_x[1]); } void VrmlSFVec2f::normalize() { float len = (float)length(); if ( FPZERO(len)) return; d_x[0] /= len; d_x[1] /= len; } void VrmlSFVec2f::add( VrmlSFVec2f *v ) { d_x[0] += v->x(); d_x[1] += v->y(); } void VrmlSFVec2f::divide( float f ) { d_x[0] /= f; d_x[1] /= f; } void VrmlSFVec2f::multiply( float f ) { d_x[0] *= f; d_x[1] *= f; } void VrmlSFVec2f::subtract( VrmlSFVec2f *v ) { d_x[0] -= v->x(); d_x[1] -= v->y(); } // SFVec3f #include "VrmlSFVec3f.h" VrmlSFVec3f::VrmlSFVec3f(float x, float y, float z) { d_x[0] = x; d_x[1] = y; d_x[2] = z; } ostream& VrmlSFVec3f::print(ostream& os) const { return (os << d_x[0] << " " << d_x[1] << " " << d_x[2]); } VrmlField *VrmlSFVec3f::clone() const { return new VrmlSFVec3f(d_x[0],d_x[1],d_x[2]); } VrmlField::VrmlFieldType VrmlSFVec3f::fieldType() const { return SFVEC3F; } double VrmlSFVec3f::dot( VrmlSFVec3f *v ) { return d_x[0] * v->x() + d_x[1] * v->y() + d_x[2] * v->z(); } double VrmlSFVec3f::length() { return sqrt(d_x[0] * d_x[0] + d_x[1] * d_x[1] + d_x[2] * d_x[2]); } void VrmlSFVec3f::normalize() { float len = (float)length(); if ( FPZERO(len)) return; d_x[0] /= len; d_x[1] /= len; d_x[2] /= len; } void VrmlSFVec3f::cross( VrmlSFVec3f *v ) { float x,y,z; // Use temps so V can be A or B x = d_x[1]*v->z() - d_x[2]*v->y(); y = d_x[2]*v->x() - d_x[0]*v->z(); z = d_x[0]*v->y() - d_x[1]*v->x(); d_x[0] = x; d_x[1] = y; d_x[2] = z; } void VrmlSFVec3f::add( VrmlSFVec3f *v ) { d_x[0] += v->x(); d_x[1] += v->y(); d_x[2] += v->z(); } void VrmlSFVec3f::divide( float f ) { d_x[0] /= f; d_x[1] /= f; d_x[2] /= f; } void VrmlSFVec3f::multiply( float f ) { d_x[0] *= f; d_x[1] *= f; d_x[2] *= f; } void VrmlSFVec3f::subtract( VrmlSFVec3f *v ) { d_x[0] -= v->x(); d_x[1] -= v->y(); d_x[2] -= v->z(); } // MFColor #include "VrmlMFColor.h" VrmlMFColor::VrmlMFColor() : d_data(new FData(0)) {} VrmlMFColor::VrmlMFColor(float r, float g, float b) : d_data(new FData(3)) { d_data->d_v[0] = r; d_data->d_v[1] = g; d_data->d_v[2] = b; } VrmlMFColor::VrmlMFColor(int n, float *v) : d_data(new FData(3*n)) { if (v) memcpy(d_data->d_v, v, 3*n*sizeof(float)); } VrmlMFColor::VrmlMFColor(const VrmlMFColor &source) : d_data(source.d_data->ref()) {} VrmlMFColor::~VrmlMFColor() { d_data->deref(); } void VrmlMFColor::set(int n, float *v) { d_data->deref(); d_data = new FData(3*n); if (v) memcpy(d_data->d_v, v, 3*n*sizeof(float)); } VrmlMFColor& VrmlMFColor::operator=(const VrmlMFColor& rhs) { if (this != &rhs) { d_data->deref(); d_data = rhs.d_data->ref(); } return *this; } VrmlField *VrmlMFColor::clone() const { return new VrmlMFColor(*this); } VrmlField::VrmlFieldType VrmlMFColor::fieldType() const { return MFCOLOR; } // MFFloat #include "VrmlMFFloat.h" VrmlMFFloat::VrmlMFFloat() : d_data(new FData(0)) {} VrmlMFFloat::VrmlMFFloat(float value) : d_data(new FData(1)) { d_data->d_v[0] = value; } VrmlMFFloat::VrmlMFFloat(int n, float* v) : d_data(new FData(n)) { if (v) memcpy(d_data->d_v, v, n*sizeof(float)); } VrmlMFFloat::VrmlMFFloat(const VrmlMFFloat &src) : d_data(src.d_data->ref()) {} VrmlMFFloat::~VrmlMFFloat() { d_data->deref(); } void VrmlMFFloat::set(int n, float *v) { d_data->deref(); d_data = new FData(n); if (v) memcpy(d_data->d_v, v, n*sizeof(float)); } VrmlMFFloat& VrmlMFFloat::operator=(const VrmlMFFloat& rhs) { if (this != &rhs) { d_data->deref(); d_data = rhs.d_data->ref(); } return *this; } VrmlField *VrmlMFFloat::clone() const { return new VrmlMFFloat(*this); } VrmlField::VrmlFieldType VrmlMFFloat::fieldType() const { return MFFLOAT; } // MFInt #include "VrmlMFInt.h" VrmlMFInt::VrmlMFInt() : d_data(new IData(0)) {} VrmlMFInt::VrmlMFInt(int value) : d_data(new IData(1)) { d_data->d_v[0] = value; } VrmlMFInt::VrmlMFInt(int n, int *v) : d_data(new IData(n)) { if (v) memcpy(d_data->d_v, v, n*sizeof(int)); } VrmlMFInt::VrmlMFInt(const VrmlMFInt &src) : d_data(src.d_data->ref()) {} VrmlMFInt::~VrmlMFInt() { d_data->deref(); } void VrmlMFInt::set(int n, int *v) { d_data->deref(); d_data = new IData(n); if (v) memcpy(d_data->d_v, v, n*sizeof(int)); } VrmlMFInt& VrmlMFInt::operator=(const VrmlMFInt& rhs) { if (this != &rhs) { d_data->deref(); d_data = rhs.d_data->ref(); } return *this; } VrmlField *VrmlMFInt::clone() const { return new VrmlMFInt(*this); } VrmlField::VrmlFieldType VrmlMFInt::fieldType() const { return MFINT32; } // MFNode #include "VrmlMFNode.h" VrmlMFNode::VrmlMFNode() : d_v(0), d_allocated(0), d_size(0) {} VrmlMFNode::VrmlMFNode(VrmlNode *value) : d_v(new VrmlNode* [1]), d_allocated(1), d_size(1) { d_v[0] = value ? value->reference() : 0; } VrmlMFNode::VrmlMFNode(int n, VrmlNode **v) : d_v(new VrmlNode* [n]), d_allocated(n), d_size(n) { if (v) for (int i=0; ireference()) : 0; else memset(d_v, 0, n * sizeof(VrmlNode*)); } VrmlMFNode::VrmlMFNode(const VrmlMFNode& rhs) : d_v(new VrmlNode* [rhs.d_size]), d_allocated(rhs.d_size), d_size(rhs.d_size) { int n = rhs.d_size; for (int i=0; ireference()) : 0; } VrmlMFNode::~VrmlMFNode() { for (int i=0; idereference(); delete [] d_v; } // Assignment. Since the nodes themselves are ref counted, we // don't bother trying to share the NodeLists. VrmlMFNode& VrmlMFNode::operator=(const VrmlMFNode& rhs) { if (this == &rhs) return *this; int i; for (i=0; i < d_size; ++i) if (d_v[i]) d_v[i]->dereference(); if (d_allocated < rhs.d_size) { delete [] d_v; d_size = d_allocated = 0; d_v = 0; d_v = new VrmlNode*[rhs.d_size]; d_allocated = rhs.d_size; } d_size = rhs.d_size; for (i=0; ireference() : 0; return *this; } VrmlField *VrmlMFNode::clone() const { return new VrmlMFNode(*this); } VrmlField::VrmlFieldType VrmlMFNode::fieldType() const { return MFNODE; } bool VrmlMFNode::exists(VrmlNode *n) { for (int i=0; ireference() : 0; } } void VrmlMFNode::removeNode(VrmlNode *n) { for (int i=0; idereference(); --d_size; break; } } // MFRotation #include "VrmlMFRotation.h" VrmlMFRotation::VrmlMFRotation() : d_data(new FData(0)) {} VrmlMFRotation::VrmlMFRotation(float x, float y, float z, float r) : d_data(new FData(4)) { d_data->d_v[0]=x; d_data->d_v[1]=y; d_data->d_v[2]=z; d_data->d_v[3]=r; } VrmlMFRotation::VrmlMFRotation(int n, float *v) : d_data(new FData(4*n)) { if (v) memcpy(d_data->d_v, v, 4*n*sizeof(float)); } VrmlMFRotation::VrmlMFRotation(const VrmlMFRotation &src) : d_data(src.d_data->ref()) {} VrmlMFRotation::~VrmlMFRotation() { d_data->deref(); } void VrmlMFRotation::set(int n, float *v) { d_data->deref(); d_data = new FData(4*n); if (v) memcpy(d_data->d_v, v, 4*n*sizeof(float)); } VrmlMFRotation& VrmlMFRotation::operator=(const VrmlMFRotation& rhs) { if (this != &rhs) { d_data->deref(); d_data = rhs.d_data->ref(); } return *this; } VrmlField *VrmlMFRotation::clone() const { return new VrmlMFRotation(*this); } VrmlField::VrmlFieldType VrmlMFRotation::fieldType() const { return MFROTATION; } // MFString #include "VrmlMFString.h" VrmlMFString::VrmlMFString() : d_v(0), d_allocated(0), d_size(0) {} VrmlMFString::VrmlMFString(char* s) : d_v(new char*[1]), d_allocated(1), d_size(1) { if (s) { d_v[0] = new char[strlen(s)+1]; strcpy(d_v[0],s); } else d_v[0] = 0; } VrmlMFString::VrmlMFString(int n, char **v) : d_v(new char*[n]), d_allocated(n), d_size(n) { if (v) for (int i=0; id_v[0] = x; d_data->d_v[1] = y; } VrmlMFVec2f::VrmlMFVec2f(int n, float *v) : d_data(new FData(2*n)) { if (v) memcpy(d_data->d_v, v, 2*n*sizeof(float)); } VrmlMFVec2f::VrmlMFVec2f(const VrmlMFVec2f &source) : d_data(source.d_data->ref()) {} VrmlMFVec2f::~VrmlMFVec2f() { d_data->deref(); } void VrmlMFVec2f::set(int n, float *v) { d_data->deref(); d_data = new FData(2*n); if (v) memcpy(d_data->d_v, v, 2*n*sizeof(float)); } VrmlMFVec2f& VrmlMFVec2f::operator=(const VrmlMFVec2f& rhs) { if (this != &rhs) { d_data->deref(); d_data = rhs.d_data->ref(); } return *this; } VrmlField *VrmlMFVec2f::clone() const { return new VrmlMFVec2f(*this); } VrmlField::VrmlFieldType VrmlMFVec2f::fieldType() const { return MFVEC2F; } // MFVec3f #include "VrmlMFVec3f.h" VrmlMFVec3f::VrmlMFVec3f(int n) : d_data(new FData(n)) {} VrmlMFVec3f::VrmlMFVec3f(float x, float y, float z) : d_data(new FData(3)) { d_data->d_v[0] = x; d_data->d_v[1] = y; d_data->d_v[2] = z; } VrmlMFVec3f::VrmlMFVec3f(int n, float *v) : d_data(new FData(3*n)) { if (v) memcpy(d_data->d_v, v, 3*n*sizeof(float)); } VrmlMFVec3f::VrmlMFVec3f(const VrmlMFVec3f &source) : d_data(source.d_data->ref()) {} VrmlMFVec3f::~VrmlMFVec3f() { d_data->deref(); } void VrmlMFVec3f::set(int n, float *v) { d_data->deref(); d_data = new FData(3*n); if (v) memcpy(d_data->d_v, v, 3*n*sizeof(float)); } VrmlMFVec3f& VrmlMFVec3f::operator=(const VrmlMFVec3f& rhs) { if (this != &rhs) { d_data->deref(); d_data = rhs.d_data->ref(); } return *this; } VrmlField *VrmlMFVec3f::clone() const { return new VrmlMFVec3f(*this); } VrmlField::VrmlFieldType VrmlMFVec3f::fieldType() const { return MFVEC3F; } // Generic MF float print function static ostream& mffprint( ostream& os, float *c, int n, int eltsize ) { int e; if (n == 1) for (e=0; e