00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <physics/Material>
00026
00027 #include <base/Application>
00028 #include <base/VFile>
00029 #include <base/Externalizer>
00030 #include <base/externalization_error>
00031 #include <base/Vector>
00032 #include <gfx/Color3>
00033 #include <gfx/Color4>
00034
00035 #include <osg/Material>
00036 #include <osg/Texture2D>
00037 #include <osg/Vec4>
00038 #include <osgDB/ReadFile>
00039
00040
00041 using base::Application;
00042 using base::VFile;
00043 using base::Vector;
00044 using base::externalization_error;
00045
00046 using base::dom::DOMNode;
00047 using base::dom::DOMElement;
00048
00049 using physics::Material;
00050 using gfx::Color3;
00051 using gfx::Color4;
00052
00053 using osg::Vec4;
00054 using osg::StateSet;
00055
00056
00057 Material::Material(const String& label, const gfx::Color4& color)
00058 : label(label), mDensity(1.0),
00059 surfaceAppearanceType(BaseColor),
00060 mBaseColor(color),
00061 stateSetCached(false)
00062 {
00063 }
00064
00065
00066 Material::Material(const Material& m)
00067 : label(m.label), mDensity(m.mDensity),
00068 surfaceAppearanceType(m.surfaceAppearanceType),
00069 mBaseColor(m.mBaseColor),
00070 surfaceTextureImage(m.surfaceTextureImage),
00071 stateSetCached(m.stateSetCached),
00072 stateSet(m.stateSet)
00073 {
00074 }
00075
00076
00077 Material::~Material()
00078 {
00079 }
00080
00081
00082 void Material::setSurfaceAppearance(const base::PathName& image)
00083 {
00084 surfaceAppearanceType = TextureImage;
00085 surfaceTextureImage = image;
00086 stateSetCached = false;
00087 }
00088
00089
00090 osg::ref_ptr<osg::StateSet> Material::createState() const
00091 {
00092 if (stateSetCached) return stateSet;
00093
00094 osg::ref_ptr<StateSet> state = new osg::StateSet();
00095 osg::ref_ptr<osg::Material> mat = new osg::Material();
00096 Vec4 col( (float)baseColor().r,
00097 (float)baseColor().g,
00098 (float)baseColor().b,
00099 (float)baseColor().a );
00100 mat->setEmission( osg::Material::FRONT_AND_BACK, Vec4(0,0,0,0) );
00101 mat->setAmbient( osg::Material::FRONT_AND_BACK, col );
00102 mat->setDiffuse( osg::Material::FRONT_AND_BACK, col );
00103 mat->setSpecular( osg::Material::FRONT_AND_BACK, Vec4(1,1,1,0) );
00104 mat->setShininess( osg::Material::FRONT_AND_BACK, 128);
00105 mat->setAlpha( osg::Material::FRONT_AND_BACK, (float)baseColor().a );
00106 state->setAttribute( &(*mat) );
00107 if (!Math::equals(baseColor().a, 1.0)) {
00108 state->setMode(GL_BLEND, osg::StateAttribute::ON);
00109 state->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
00110 }
00111
00112 if (surfaceAppearanceType == TextureImage) {
00113
00114 ref<VFile> imageFile(Application::getInstance()->universe()->cache()->findFile(surfaceTextureImage));
00115
00116
00117
00118
00119 String filename( imageFile->pathName().str() );
00120
00121 osg::ref_ptr<osg::Image> image = osgDB::readImageFile(filename);
00122 if (image == (osg::Image*)0)
00123 throw std::runtime_error(Exception(String("unable to read texture image file:")+filename));
00124
00125 osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D();
00126 texture->setImage(&(*image));
00127 texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR_MIPMAP_NEAREST);
00128 texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
00129 texture->setInternalFormatMode(osg::Texture2D::USE_ARB_COMPRESSION);
00130 texture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::REPEAT);
00131 texture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::REPEAT);
00132
00133 state->setTextureAttributeAndModes(0,&(*texture),osg::StateAttribute::ON);
00134 }
00135
00136 stateSetCached = true;
00137 stateSet = state;
00138
00139 return stateSet;
00140 }
00141
00142
00143 void Material::externalize(base::Externalizer& e, String format, Real version)
00144 {
00145 if (format=="") format="xml";
00146
00147 if (!formatSupported(format,version,e.ioType()))
00148 throw std::invalid_argument(Exception(String("format ")+format+" v"+base::realToString(version)+" unsupported"));
00149
00150 if (format == "xml") {
00151
00152 if (e.isOutput()) {
00153
00154 DOMElement* matElem = e.createElement("material");
00155 e.setElementAttribute(matElem,"name",label);
00156 e.setElementAttribute(matElem,"type","simple");
00157
00158 DOMElement* dElem = e.createElement("density",false);
00159 e.appendText(dElem, base::realToString(mDensity));
00160 e.appendNode(matElem,dElem);
00161 e.appendBreak(matElem);
00162
00163 DOMElement* cElem = e.createElement("basecolor",false);
00164 Vector c(3);
00165 c[0]=mBaseColor.r; c[1]=mBaseColor.g; c[2]=mBaseColor.b;
00166 e.appendText(cElem, e.toString(c,true));
00167 e.appendNode(matElem,cElem);
00168
00169 if (surfaceAppearanceType == TextureImage) {
00170 DOMElement* saElem = e.createElement("surfaceappearance",false);
00171 e.setElementAttribute(saElem,"type","image");
00172 e.appendText(saElem, surfaceTextureImage.str() );
00173 e.appendNode(matElem,saElem);
00174 }
00175
00176 e.appendElement(matElem);
00177
00178 }
00179 else {
00180
00181 DOMNode* context = e.context();
00182
00183 DOMElement* matElem = e.getFirstChildElement(context, "material");
00184
00185 if ( e.getElementAttribute(matElem, "type") != "simple" )
00186 throw externalization_error(Exception("unsupported material type"));
00187
00188 label = e.getDefaultedElementAttribute(matElem, "name", "untitled");
00189
00190 DOMElement* dElem = e.getFirstChildElement(matElem, "density", false);
00191 if (dElem) {
00192 String densityText = e.getContainedText(dElem);
00193 mDensity = base::stringToReal(densityText);
00194 }
00195 else
00196 mDensity=1.0;
00197
00198 surfaceAppearanceType = BaseColor;
00199 DOMElement* cElem = e.getFirstChildElement(matElem, "basecolor",false);
00200 if (cElem) {
00201 String colorText = e.getContainedText(cElem);
00202 Vector3 cv( e.toVector3(colorText) );
00203 mBaseColor = Color3(cv.x,cv.y,cv.z);
00204 }
00205 else
00206 mBaseColor = Color3(0,1,0);
00207
00208
00209 DOMElement* saElem = e.getFirstChildElement(matElem, "surfaceappearance",false);
00210 if (saElem) {
00211 String type = e.getDefaultedElementAttribute(saElem,"type","image");
00212 if (type == "image") {
00213 surfaceAppearanceType = TextureImage;
00214 surfaceTextureImage = e.getContainedText(saElem);
00215 }
00216 else
00217 throw externalization_error(Exception("unsupported value of 'type' attribute of element 'surfaceappearance'"));
00218 }
00219
00220
00221
00222 e.removeElement(matElem);
00223
00224 }
00225
00226 }
00227
00228 }
00229