I have had another go at the windows specific file name handling in
daeWMaterials.cpp. I think I have arrived at a temporary compromise.

I have decided to just normalise the drive letter part of file names for the
time being and also ensure that names of the format x:/xxxxx are treated as
absolute paths. This will cover a lot of cases.

 

I have raised a bug against collada which hopefully should resolve some
others. However there are some pathological cases which I have commented on
in the code, these will probably never work properly unless there is a
significant rewrite of the daeURI functionality. Hopefully they are rare.

 

Zach, your test case now works. However the plugin does not support
billboards at the moment (I have not checked the Collada spec on this). So
your tree appears one sided!

 

Roger

/*
 * Copyright 2006 Sony Computer Entertainment Inc.
 *
 * Licensed under the SCEA Shared Source License, Version 1.0 (the "License"); 
you may not use this 
 * file except in compliance with the License. You may obtain a copy of the 
License at:
 * http://research.scea.com/scea_shared_source_license.html
 *
 * Unless required by applicable law or agreed to in writing, software 
distributed under the License 
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express or 
 * implied. See the License for the specific language governing permissions and 
limitations under the 
 * License. 
 */

#include "daeWriter.h"

#include <dae/domAny.h>
#include <dom/domCOLLADA.h>
#include <dom/domConstants.h>
#include <dom/domProfile_COMMON.h>

#include <sstream>

//#include <dom/domLibrary_effects.h>
//#include <dom/domLibrary_materials.h>

using namespace osgdae;

void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, 
const std::string &geoName )
{
    osg::ref_ptr<osg::StateSet> ssClean = CleanStateSet(ss); // Need to hold a 
ref to this or the materialMap.find() will delete it
    domBind_material *bm = daeSafeCast< domBind_material >( ig->createAndPlace( 
COLLADA_ELEMENT_BIND_MATERIAL ) );
    domBind_material::domTechnique_common *tc = daeSafeCast< 
domBind_material::domTechnique_common >( bm->createAndPlace( "technique_common" 
) );
    domInstance_material *im = daeSafeCast< domInstance_material >( 
tc->createAndPlace( COLLADA_ELEMENT_INSTANCE_MATERIAL ) );
    std::string symbol = geoName + "_material";
    im->setSymbol( symbol.c_str() );

    MaterialMap::iterator iter = materialMap.find( ssClean );
    if ( iter != materialMap.end() )
    {
        std::string url = "#" + std::string( iter->second->getId() );
        im->setTarget( url.c_str() );
        return;
    }

    if ( lib_mats == NULL )
    {
        lib_mats = daeSafeCast< domLibrary_materials >( dom->createAndPlace( 
COLLADA_ELEMENT_LIBRARY_MATERIALS ) );
    }

    domMaterial *mat = daeSafeCast< domMaterial >( lib_mats->createAndPlace( 
COLLADA_ELEMENT_MATERIAL ) );
    std::string name = ssClean->getName();
    if ( name.empty() )
    {
        name = "material";
    }
    name = uniquify( name );

    mat->setId( name.c_str() );

    std::string url = "#" + name;
    im->setTarget( url.c_str() );

    domInstance_effect *ie = daeSafeCast<domInstance_effect>( 
mat->createAndPlace( "instance_effect" ) );

    if ( lib_effects == NULL )
    {
        lib_effects = daeSafeCast< domLibrary_effects >( dom->createAndPlace( 
COLLADA_ELEMENT_LIBRARY_EFFECTS ) );
    }
    domEffect *effect = daeSafeCast< domEffect >( lib_effects->createAndPlace( 
COLLADA_ELEMENT_EFFECT ) );
    std::string efName = name + "_effect";
    
    effect->setId( efName.c_str() );

    url = "#" + efName;
    ie->setUrl( url.c_str() );

    domProfile_COMMON *pc = daeSafeCast< domProfile_COMMON >( 
effect->createAndPlace( COLLADA_ELEMENT_PROFILE_COMMON ) );
    domProfile_COMMON::domTechnique *pc_teq = daeSafeCast< 
domProfile_COMMON::domTechnique >( pc->createAndPlace( "technique" ) );
    pc_teq->setSid( "t0" );
    domProfile_COMMON::domTechnique::domPhong *phong = daeSafeCast< 
domProfile_COMMON::domTechnique::domPhong >( pc_teq->createAndPlace( "phong" ) 
);

    osg::Texture *tex = 
static_cast<osg::Texture*>(ssClean->getTextureAttribute( 0, 
osg::StateAttribute::TEXTURE ));
    if ( ssClean->getTextureAttribute( 1, osg::StateAttribute::TEXTURE ) != 
NULL )
    {
        tex = static_cast<osg::Texture*>(ssClean->getTextureAttribute( 1, 
osg::StateAttribute::TEXTURE ));
    }
    if ( tex != NULL && tex->getImage( 0 ) != NULL )
    {
        //TODO: Export all of the texture Attributes like wrap mode and all 
that jazz
        domImage *img = daeSafeCast< domImage >( pc->createAndPlace( 
COLLADA_ELEMENT_IMAGE ) );
        std::string iName = efName + "-image";
        img->setId( iName.c_str() );

        osg::Image *osgimg = tex->getImage( 0 );
        domImage::domInit_from *imgif = daeSafeCast< domImage::domInit_from >( 
img->createAndPlace( "init_from" ) );
        std::string imgstr = osgDB::convertFileNameToUnixStyle( 
osgDB::findDataFile( osgimg->getFileName() ) );
#ifdef WIN32
                // At this point imgstr might contain something like "c:/xxxx" 
which should be treated
                // as an absolute path. In this case I will prepend a / and 
normalise the drive letter to upper case.
                //
                // There are also a number of valid windows path formats
                // such as UNC names which will appear like this at this point
                // //sharename/filepath
                // and volume names which will appear like this at this point
                // //?/{guid}/   where guid is a multi digit number
                // In fact //?/ can be prepended to any path and is some wierd 
windows specific marker
                // File paths of these formats are almost guaranteed to break 
the dae URI code.
                //
                if ((imgstr.length() > 3) && (isalpha(imgstr[0])) && (imgstr[1] 
== ':') && (imgstr[2] == '/'))
                {
                        if (islower(imgstr[0]))
                                imgstr[0] = (char)_toupper(imgstr[0]);
                        imgstr = '/' + imgstr;
                }
#endif
        daeURI uri( imgstr.c_str() );
        uri.validate(); // This returns an absolute URI
        imgif->setValue( uri.getURI() );
        imgif->getValue().makeRelativeTo( doc->getDocumentURI() ); 

#ifndef EARTH_TEX
        domCommon_newparam_type *np = daeSafeCast< domCommon_newparam_type >( 
pc->createAndPlace( "newparam" ) );
        std::string surfName = efName + "-surface";
        np->setSid( surfName.c_str() );
        domFx_surface_common *surface = daeSafeCast< domFx_surface_common >( 
np->createAndPlace( "surface" ) );
        domFx_surface_init_from_common *sif = daeSafeCast< 
domFx_surface_init_from_common >( surface->createAndPlace("init_from") );
        sif->setValue( iName.c_str() );
        surface->setType( FX_SURFACE_TYPE_ENUM_2D );

        np = daeSafeCast< domCommon_newparam_type >( pc->createAndPlace( 
"newparam" ) );
        std::string sampName = efName + "-sampler";
        np->setSid( sampName.c_str() );
        domFx_sampler2D_common *sampler = daeSafeCast< domFx_sampler2D_common 
>( np->createAndPlace( "sampler2D" ) );
        domFx_sampler2D_common_complexType::domSource *source = daeSafeCast< 
domFx_sampler2D_common_complexType::domSource >( sampler->createAndPlace( 
"source" ) );
        source->setValue( surfName.c_str() ); 

        //set sampler state
        domFx_sampler2D_common_complexType::domWrap_s *wrap_s = daeSafeCast< 
domFx_sampler2D_common_complexType::domWrap_s >( sampler->createAndPlace( 
"wrap_s" ) );
        osg::Texture::WrapMode wrap = tex->getWrap( osg::Texture::WRAP_S );
        switch( wrap ) 
        {
        case osg::Texture::CLAMP:
            wrap_s->setValue( FX_SAMPLER_WRAP_COMMON_CLAMP );
            break;
        case osg::Texture::CLAMP_TO_BORDER:
        case osg::Texture::CLAMP_TO_EDGE:
            wrap_s->setValue( FX_SAMPLER_WRAP_COMMON_BORDER );
            break;
        case osg::Texture::REPEAT:
            wrap_s->setValue( FX_SAMPLER_WRAP_COMMON_WRAP );
            break;
        case osg::Texture::MIRROR:
            wrap_s->setValue( FX_SAMPLER_WRAP_COMMON_MIRROR );
            break;
        default:
            wrap_s->setValue( FX_SAMPLER_WRAP_COMMON_NONE );
            break;
        }

        domFx_sampler2D_common_complexType::domWrap_t *wrap_t = daeSafeCast< 
domFx_sampler2D_common_complexType::domWrap_t >( sampler->createAndPlace( 
"wrap_t" ) );
        wrap = tex->getWrap( osg::Texture::WRAP_T );
        switch( wrap ) 
        {
        case osg::Texture::CLAMP:
            wrap_t->setValue( FX_SAMPLER_WRAP_COMMON_CLAMP );
            break;
        case osg::Texture::CLAMP_TO_BORDER:
        case osg::Texture::CLAMP_TO_EDGE:
            wrap_t->setValue( FX_SAMPLER_WRAP_COMMON_BORDER );
            break;
        case osg::Texture::REPEAT:
            wrap_t->setValue( FX_SAMPLER_WRAP_COMMON_WRAP );
            break;
        case osg::Texture::MIRROR:
            wrap_t->setValue( FX_SAMPLER_WRAP_COMMON_MIRROR );
            break;
        default:
            wrap_t->setValue( FX_SAMPLER_WRAP_COMMON_NONE );
            break;
        }

        const osg::Vec4 &bcol = tex->getBorderColor();
        domFx_sampler2D_common_complexType::domBorder_color *dbcol = 
daeSafeCast< domFx_sampler2D_common_complexType::domBorder_color >( 
sampler->createAndPlace( "border_color" ) );
        dbcol->getValue().append( bcol.r() );
        dbcol->getValue().append( bcol.g() );
        dbcol->getValue().append( bcol.b() );
        dbcol->getValue().append( bcol.a() );

        domFx_sampler2D_common_complexType::domMinfilter *minfilter = 
daeSafeCast< domFx_sampler2D_common_complexType::domMinfilter >( 
sampler->createAndPlace( "minfilter" ) );
        osg::Texture::FilterMode mode = tex->getFilter( 
osg::Texture::MIN_FILTER );
        switch( mode )
        {
        case osg::Texture::LINEAR:
            minfilter->setValue( FX_SAMPLER_FILTER_COMMON_LINEAR );
            break;
        case osg::Texture::LINEAR_MIPMAP_LINEAR:
            minfilter->setValue( FX_SAMPLER_FILTER_COMMON_LINEAR_MIPMAP_LINEAR 
);
            break;
        case osg::Texture::LINEAR_MIPMAP_NEAREST:
            minfilter->setValue( FX_SAMPLER_FILTER_COMMON_LINEAR_MIPMAP_NEAREST 
);
            break;
        case osg::Texture::NEAREST:
            minfilter->setValue( FX_SAMPLER_FILTER_COMMON_NEAREST );
            break;
        case osg::Texture::NEAREST_MIPMAP_LINEAR:
            minfilter->setValue( FX_SAMPLER_FILTER_COMMON_NEAREST_MIPMAP_LINEAR 
);
            break;
        case osg::Texture::NEAREST_MIPMAP_NEAREST:
            minfilter->setValue( 
FX_SAMPLER_FILTER_COMMON_NEAREST_MIPMAP_NEAREST );
            break;
        }

        domFx_sampler2D_common_complexType::domMagfilter *magfilter = 
daeSafeCast< domFx_sampler2D_common_complexType::domMagfilter >( 
sampler->createAndPlace( "magfilter" ) );
        mode = tex->getFilter( osg::Texture::MAG_FILTER );
        switch( mode )
        {
        case osg::Texture::LINEAR:
            magfilter->setValue( FX_SAMPLER_FILTER_COMMON_LINEAR );
            break;
        case osg::Texture::LINEAR_MIPMAP_LINEAR:
            magfilter->setValue( FX_SAMPLER_FILTER_COMMON_LINEAR_MIPMAP_LINEAR 
);
            break;
        case osg::Texture::LINEAR_MIPMAP_NEAREST:
            magfilter->setValue( FX_SAMPLER_FILTER_COMMON_LINEAR_MIPMAP_NEAREST 
);
            break;
        case osg::Texture::NEAREST:
            magfilter->setValue( FX_SAMPLER_FILTER_COMMON_NEAREST );
            break;
        case osg::Texture::NEAREST_MIPMAP_LINEAR:
            magfilter->setValue( FX_SAMPLER_FILTER_COMMON_NEAREST_MIPMAP_LINEAR 
);
            break;
        case osg::Texture::NEAREST_MIPMAP_NEAREST:
            magfilter->setValue( 
FX_SAMPLER_FILTER_COMMON_NEAREST_MIPMAP_NEAREST );
            break;
        }


        domCommon_color_or_texture_type *cot = daeSafeCast< 
domCommon_color_or_texture_type >( phong->createAndPlace( "diffuse" ) );
        domCommon_color_or_texture_type_complexType::domTexture *dtex = 
daeSafeCast< domCommon_color_or_texture_type_complexType::domTexture >( 
cot->createAndPlace( "texture" ) );
        dtex->setTexture( sampName.c_str() );
        dtex->setTexcoord( "texcoord0" );
#else
        domCommon_color_or_texture_type *cot = daeSafeCast< 
domCommon_color_or_texture_type >( phong->createAndPlace( "diffuse" ) );
        domCommon_color_or_texture_type_complexType::domTexture *dtex = 
daeSafeCast< domCommon_color_or_texture_type_complexType::domTexture >( 
cot->createAndPlace( "texture" ) );
        dtex->setTexture( iName.c_str() );
        dtex->setTexcoord( "texcoord0" );
#endif

        domInstance_material::domBind_vertex_input *bvi = daeSafeCast< 
domInstance_material::domBind_vertex_input >( im->createAndPlace( 
"bind_vertex_input" ) );
        bvi->setSemantic( "texcoord0" );
        bvi->setInput_semantic( "TEXCOORD" );
        bvi->setInput_set( 0 );

        //take care of blending if any
        osg::BlendFunc *bf = static_cast< osg::BlendFunc * >( 
ssClean->getAttribute( osg::StateAttribute::BLENDFUNC ) );
        osg::BlendColor *bc = static_cast< osg::BlendColor * >( 
ssClean->getAttribute( osg::StateAttribute::BLENDCOLOR ) );
        if ( bc != NULL )
        {
            domCommon_transparent_type *ctt = daeSafeCast< 
domCommon_transparent_type >( phong->createAndPlace( "transparent" ) );
            ctt->setOpaque( FX_OPAQUE_ENUM_RGB_ZERO );
            domCommon_color_or_texture_type_complexType::domColor *tcol = 
daeSafeCast< domCommon_color_or_texture_type_complexType::domColor >( 
ctt->createAndPlace( "color" ) );
            tcol->getValue().append( bc->getConstantColor().r() );
            tcol->getValue().append( bc->getConstantColor().r() );
            tcol->getValue().append( bc->getConstantColor().r() );
            tcol->getValue().append( bc->getConstantColor().r() );
        }
        else if ( bf != NULL )
        {
            domCommon_transparent_type *ctt = daeSafeCast< 
domCommon_transparent_type >( phong->createAndPlace( "transparent" ) );
            ctt->setOpaque( FX_OPAQUE_ENUM_A_ONE );
            dtex = daeSafeCast< 
domCommon_color_or_texture_type_complexType::domTexture >( ctt->createAndPlace( 
"texture" ) );
#ifndef EARTH_TEX
            dtex->setTexture( sampName.c_str() );
#else
            dtex->setTexture( iName.c_str() );
#endif
            dtex->setTexcoord( "texcoord0" );           
        }
        
    }
    osg::Material *osgmat = static_cast<osg::Material*>(ssClean->getAttribute( 
osg::StateAttribute::MATERIAL ));
    if ( osgmat != NULL )
    {
        const osg::Vec4 &eCol = 
osgmat->getEmissionFrontAndBack()?osgmat->getEmission( 
osg::Material::FRONT_AND_BACK ):osgmat->getEmission( osg::Material::FRONT );
        const osg::Vec4 &aCol = 
osgmat->getAmbientFrontAndBack()?osgmat->getAmbient( 
osg::Material::FRONT_AND_BACK ):osgmat->getAmbient( osg::Material::FRONT );
        const osg::Vec4 &dCol = 
osgmat->getDiffuseFrontAndBack()?osgmat->getDiffuse( 
osg::Material::FRONT_AND_BACK ):osgmat->getDiffuse( osg::Material::FRONT );
        const osg::Vec4 &sCol = 
osgmat->getSpecularFrontAndBack()?osgmat->getSpecular( 
osg::Material::FRONT_AND_BACK ):osgmat->getSpecular( osg::Material::FRONT );
        float shininess = 
osgmat->getShininessFrontAndBack()?osgmat->getShininess( 
osg::Material::FRONT_AND_BACK ):osgmat->getShininess( osg::Material::FRONT );
        
        domCommon_color_or_texture_type *cot = daeSafeCast< 
domCommon_color_or_texture_type >( phong->createAndPlace( "emission" ) );
        domCommon_color_or_texture_type_complexType::domColor *col = 
daeSafeCast< domCommon_color_or_texture_type_complexType::domColor >( 
cot->createAndPlace( "color" ) );
        col->getValue().append( eCol.r() );
        col->getValue().append( eCol.g() );
        col->getValue().append( eCol.b() );
        col->getValue().append( eCol.a() );

        cot = daeSafeCast< domCommon_color_or_texture_type >( 
phong->createAndPlace( "ambient" ) );
        col = daeSafeCast< 
domCommon_color_or_texture_type_complexType::domColor >( cot->createAndPlace( 
"color" ) );
        col->getValue().append( aCol.r() );
        col->getValue().append( aCol.g() );
        col->getValue().append( aCol.b() );
        col->getValue().append( aCol.a() );

        
        //### check if we really have a texture
        if ( phong->getDiffuse() == NULL )
        {
            cot = daeSafeCast< domCommon_color_or_texture_type >( 
phong->createAndPlace( "diffuse" ) );
            col = daeSafeCast< 
domCommon_color_or_texture_type_complexType::domColor >( cot->createAndPlace( 
"color" ) );
            col->getValue().append( dCol.r() );
            col->getValue().append( dCol.g() );
            col->getValue().append( dCol.b() );
            col->getValue().append( dCol.a() );
        }
        else
        {
            cot = phong->getDiffuse();
            
            domCommon_color_or_texture_type_complexType::domTexture *dtex = 
cot->getTexture();
            domExtra *extra = daeSafeCast< domExtra >( dtex->createAndPlace( 
COLLADA_ELEMENT_EXTRA ) );
            extra->setType( "color" );
            domTechnique *teq = daeSafeCast< domTechnique >( 
extra->createAndPlace( COLLADA_ELEMENT_TECHNIQUE ) );
            teq->setProfile( "SCEI" );
            domAny *any = (domAny*)(daeElement*)teq->createAndPlace( "color" );

            std::ostringstream colVal;
            colVal << dCol.r() << " " << dCol.g() << " " << dCol.b() << " " << 
dCol.a();
            any->setValue( colVal.str().c_str() );
        }

        cot = daeSafeCast< domCommon_color_or_texture_type >( 
phong->createAndPlace( "specular" ) );
        col = daeSafeCast< 
domCommon_color_or_texture_type_complexType::domColor >( cot->createAndPlace( 
"color" ) );
        col->getValue().append( sCol.r() );
        col->getValue().append( sCol.g() );
        col->getValue().append( sCol.b() );
        col->getValue().append( sCol.a() );

        domCommon_float_or_param_type *fop = daeSafeCast< 
domCommon_float_or_param_type >( phong->createAndPlace( "shininess" ) );
        domCommon_float_or_param_type_complexType::domFloat *f = daeSafeCast< 
domCommon_float_or_param_type_complexType::domFloat >( fop->createAndPlace( 
"float" ) );
        f->setValue( shininess );
    }

    materialMap.insert( std::make_pair( ssClean, mat ) );
}

osg::StateSet* daeWriter::CleanStateSet(osg::StateSet* pStateSet) const
{
    // TODO - clean out all the the attributes and modes not used to define 
materials
    osg::StateSet* pCleanedStateSet = new osg::StateSet;
    
pCleanedStateSet->setTextureAttributeList(pStateSet->getTextureAttributeList());
    if (NULL != pStateSet->getAttribute(osg::StateAttribute::BLENDFUNC))
        
pCleanedStateSet->setAttribute(pStateSet->getAttribute(osg::StateAttribute::BLENDFUNC));
    if (NULL != pStateSet->getAttribute(osg::StateAttribute::BLENDCOLOR))
        
pCleanedStateSet->setAttribute(pStateSet->getAttribute(osg::StateAttribute::BLENDCOLOR));
    if (NULL != pStateSet->getAttribute(osg::StateAttribute::MATERIAL))
        
pCleanedStateSet->setAttribute(pStateSet->getAttribute(osg::StateAttribute::MATERIAL));

    return pCleanedStateSet;
}

_______________________________________________
osg-users mailing list
[email protected]
http://openscenegraph.net/mailman/listinfo/osg-users
http://www.openscenegraph.org/

Reply via email to