/**************************************************************************\ * * This file is part of the Coin 3D visualization library. * Copyright (C) 1998-2007 by Systems in Motion. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * ("GPL") version 2 as published by the Free Software Foundation. * See the file LICENSE.GPL at the root directory of this source * distribution for additional information about the GNU GPL. * * For using Coin with software that can not be combined with the GNU * GPL, and for taking advantage of the additional benefits of our * support services, please contact Systems in Motion about acquiring * a Coin Professional Edition License. * * See http://www.coin3d.org/ for more information. * * Systems in Motion, Postboks 1283, Pirsenteret, 7462 Trondheim, NORWAY. * http://www.sim.no/ sales@sim.no coin-support@coin3d.org * \**************************************************************************/ // This file contains various functions that are shared between two or // more field classes. // // Typically there's some common code for both the single-field value // and multiple-field value version of the same field-type. // ************************************************************************* // FIXME: SoSFEnum and SoMFEnum could probably share some of their // read / write code. Ditto for SoSFImage and SoSFImage3. If so, it // should be collected here. 20040630 mortene. // ************************************************************************* #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // ************************************************************************* // Read boolean value from input stream, return TRUE if // successful. Used from SoSFBool and SoMFBool. SbBool sosfbool_read_value(SoInput * in, SbBool & val) { // accept 0 or 1 if (in->read(val)) { if (val != 0 && val != 1) { SoReadError::post(in, "Illegal value for field: %d (must be 0 or 1)", val); return FALSE; } return TRUE; } if (in->isBinary()) { SoReadError::post(in, "Premature end of file"); return FALSE; } // read TRUE/FALSE keyword SbName n; if (!in->read(n, TRUE)) { SoReadError::post(in, "Couldn't read field value"); return FALSE; } if (n == "TRUE") { val = TRUE; return TRUE; } if (n == "FALSE") { val = FALSE; return TRUE; } SoReadError::post(in, "Invalid value \"%s\" for field (must be TRUE or FALSE)", n.getString()); return FALSE; } // Write boolean value to output stream. Used from SoSFBool and // SoMFBool. void sosfbool_write_value(SoOutput * out, SbBool val) { if (out->isBinary()) out->write((unsigned int)(val ? 1 : 0)); else out->write(val ? "TRUE" : "FALSE"); } // ************************************************************************* // Write floating point value to output stream. Used from SoSFFloat // and SoMFFloat. void sosffloat_write_value(SoOutput * out, float val) { out->write(val); } // ************************************************************************* // Write SbString value to output stream. Used from SoSFString and // SoMFString. void sosfstring_write_value(const SoField * f, SoOutput * out, const SbString & val) { // VRML97 needs backslashes themselves to be backslash-quoted (like // in e.g. C strings), which is taken care of here instead of // downstream, as this is the last place we can find out whether or // not we're writing a VRML97 node. const SoFieldContainer * fc = f->getContainer(); if (fc && fc->isOfType(SoNode::getClassTypeId()) && (((SoNode *)fc)->getNodeType() & SoNode::VRML2)) { // FIXME: SbString should have had a replaceAll() method, so we // wouldn't have to spell out the iteration loop below. 20040614 mortene. SbString ws; for (int i = 0; i < val.getLength(); i++) { if (val[i] == '\\') { ws += '\\'; } ws += val[i]; } out->write(ws); } else { // *Not* a VRML97 node, so write backslashes verbatim, as // dictated by the Inventor file format: out->write(val); } } // ************************************************************************* // Write matrix to output stream. Used from SoSFMatrix and SoMFMatrix. void sosfmatrix_write_value(SoOutput * out, const SbMatrix & m) { if (out->isBinary()) { for(int i = 0; i < 4; i++) { for(int j = 0; j < 4; j++) { out->write(m[i][j]); } } return; } for(int k=0; k < 4; k++) { out->write(m[0][k]); if(k != 3) out->write(' '); } out->write('\n'); out->incrementIndent(); for(int i=1; i < 4; i++) { out->indent(); for(int j=0; j < 4; j++) { out->write(m[i][j]); if(j != 3) out->write(' '); } if(i != 3) out->write('\n'); } out->decrementIndent(); } // ************************************************************************* // Read SbPlane from input stream, return TRUE if successful. Used // from SoSFPlane and SoMFPlane. SbBool sosfplane_read_value(SoInput * in, SbPlane & p) { float f[4]; for (int i = 0; i < 4; i++) { if (!in->read(f[i])) return FALSE; } p = SbPlane(SbVec3f(f[0], f[1], f[2]), f[3]); return TRUE; } // Write SbPlane value to output stream. Used from SoSFPlane and // SoMFPlane. void sosfplane_write_value(SoOutput * out, const SbPlane & p) { out->write(p.getNormal()[0]); if (!out->isBinary()) out->write(' '); out->write(p.getNormal()[1]); if (!out->isBinary()) out->write(' '); out->write(p.getNormal()[2]); if (!out->isBinary()) out->write(" "); out->write(p.getDistanceFromOrigin()); } // ************************************************************************* // Read rotation value from input stream, return TRUE if // successful. Used from SoSFRotation and SoMFRotation. SbBool sosfrotation_read_value(SoInput * in, SbRotation & r) { float f[4]; for (int i = 0; i < 4; i++) { if (!in->read(f[i])) return FALSE; } SbVec3f axis(f[0], f[1], f[2]); const float angle = f[3]; // vrml97 identity rotations are often specified with a null vector. // test for this and just set to z-axis. if (axis == SbVec3f(0.0f, 0.0f, 0.0f) && angle == 0.0f) { axis = SbVec3f(0.0f, 0.0f, 1.0f); } r.setValue(axis, angle); return TRUE; } // Write SbRotation to output stream. Used from SoSFRotation and // SoMFRotation. void sosfrotation_write_value(SoOutput * out, const SbRotation & r) { SbVec3f axis; float angle; r.getValue(axis, angle); // Handle invalid rotation specifications. if (axis.length() == 0.0f) { axis.setValue(0.0f, 0.0f, 1.0f); angle = 0.0f; } out->write(axis[0]); if(!out->isBinary()) out->write(' '); out->write(axis[1]); if(!out->isBinary()) out->write(' '); out->write(axis[2]); if(!out->isBinary()) out->write(" "); out->write(angle); } // ************************************************************************* // Write integer value to output stream. Used from SoSFShort and // SoMFShort. void sosfshort_write_value(SoOutput * out, short val) { out->write(val); } // ************************************************************************* // Read SbTime from input stream, return TRUE if successful. Used from // SoSFTime and SoMFTime. SbBool sosftime_read_value(SoInput * in, SbTime & t) { double val; if (!in->read(val)) { SoReadError::post(in, "unable to read floating point value"); return FALSE; } if (!coin_finite(val)) { SoReadError::post(in, "Detected non-valid floating point number, replacing " "with 0.0f"); val = 0.0; // We don't return FALSE, thereby allowing the read process to // continue, as a convenience for the application programmer. } t.setValue(val); return TRUE; } // Write SbTime value to output stream. Used from SoSFTime and // SoMFTime. void sosftime_write_value(SoOutput * out, const SbTime & p) { out->write(p.getValue()); } // ************************************************************************* // Write integer value to output stream. Used from SoSFUInt32 and // SoMFUInt32. void sosfuint32_write_value(SoOutput * out, uint32_t val) { unsigned int tmp = (unsigned int) val; out->write(tmp); } // ************************************************************************* // Write integer value to output stream. Used from SoSFUShort and // SoMFUShort. void sosfushort_write_value(SoOutput * out, unsigned short val) { out->write(val); } // ************************************************************************* // Write to output stream. Used from SoSFVec2f and SoMFVec2f. void sosfvec2f_write_value(SoOutput * out, const SbVec2f & v) { out->write(v[0]); if (!out->isBinary()) out->write(' '); out->write(v[1]); } // ************************************************************************* // Read from input stream, return TRUE if successful. Used from // SoSFVec3d and SoMFVec3f. SbBool sosfvec3d_read_value(SoInput * in, SbVec3d & v) { if (!in->read(v[0]) || !in->read(v[1]) || !in->read(v[2])) { SoReadError::post(in, "Couldn't read vector"); return FALSE; } return TRUE; } // Write to output stream. Used from SoSFVec3d and SoMFVec3d. void sosfvec3d_write_value(SoOutput * out, const SbVec3d & v) { out->write(v[0]); if (!out->isBinary()) out->write(' '); out->write(v[1]); if (!out->isBinary()) out->write(' '); out->write(v[2]); } // ************************************************************************* // Write to output stream. Used from SoSFVec3f, SoMFVec3f, and // SoSFColor. void sosfvec3f_write_value(SoOutput * out, const SbVec3f & v) { out->write(v[0]); if (!out->isBinary()) out->write(' '); out->write(v[1]); if (!out->isBinary()) out->write(' '); out->write(v[2]); } // ************************************************************************* // Write to output stream. Used from SoSFVec4f and SoMFVec4f. void sosfvec4f_write_value(SoOutput * out, const SbVec4f & v) { out->write(v[0]); if (!out->isBinary()) out->write(' '); out->write(v[1]); if (!out->isBinary()) out->write(' '); out->write(v[2]); if (!out->isBinary()) out->write(' '); out->write(v[3]); } // *************************************************************************