// // Vrml 97 library // Copyright (C) 1998 Chris Morley // // %W% %G% // VrmlNodeImageTexture.cpp #include "VrmlNodeImageTexture.h" #include "VRMLImage.h" #include "VrmlNodeType.h" #include "VrmlScene.h" #include "Doc.h" #if defined AW_NEW_IOSTREAMS # include #else # include #endif static VrmlNode *creator( VrmlScene *s ) { return new VrmlNodeImageTexture(s); } const VrmlMFString& VrmlNodeImageTexture::getUrl() const { return d_url; } VrmlNodeImageTexture* VrmlNodeImageTexture::toImageTexture() const { return (VrmlNodeImageTexture*) this; } // Define the built in VrmlNodeType:: "ImageTexture" fields VrmlNodeType *VrmlNodeImageTexture::defineType(VrmlNodeType *t) { static VrmlNodeType *st = 0; if (! t) { if (st) return st; t = st = new VrmlNodeType("ImageTexture", creator); } VrmlNodeTexture::defineType(t); // Parent class t->addExposedField("url", VrmlField::MFSTRING); t->addField("repeatS", VrmlField::SFBOOL); t->addField("repeatT", VrmlField::SFBOOL); return t; } VrmlNodeImageTexture::VrmlNodeImageTexture(VrmlScene *scene) : VrmlNodeTexture(scene), d_repeatS(true), d_repeatT(true), d_image(0), d_texObject(0) { } VrmlNodeType *VrmlNodeImageTexture::nodeType() const { return defineType(0); } VrmlNodeImageTexture::~VrmlNodeImageTexture() { delete d_image; // delete d_texObject... } VrmlNode *VrmlNodeImageTexture::cloneMe() const { return new VrmlNodeImageTexture(*this); } ostream& VrmlNodeImageTexture::printFields(ostream& os, int indent) { if (d_url.get()) PRINT_FIELD(url); if (! d_repeatS.get()) PRINT_FIELD(repeatS); if (! d_repeatT.get()) PRINT_FIELD(repeatT); return os; } void VrmlNodeImageTexture::render(Viewer *viewer) { if ( isModified() ) { if (d_image) { delete d_image; // URL is the only modifiable bit d_image = 0; } if (d_texObject) { viewer->removeTextureObject(d_texObject); d_texObject = 0; } } // should probably read the image during addToScene... // should cache on url so multiple references to the same file are // loaded just once... of course world authors should just DEF/USE // them... if (! d_image && d_url.size() > 0) { const char *relUrl = d_relativeUrl.get() ? d_relativeUrl.get() : d_scene->urlDoc()->url(); Doc relDoc(relUrl); d_image = new Image; if ( ! d_image->tryURLs( d_url.size(), d_url.get(), &relDoc ) ) cerr << "Error: couldn't read ImageTexture from URL " << d_url << endl; } // Check texture cache if (d_texObject && d_image) { viewer->insertTextureReference(d_texObject, d_image->nc()); } else { unsigned char *pix; if (d_image && (pix = d_image->pixels())) { // Ensure the image dimensions are powers of two int sizes[] = { 2, 4, 8, 16, 32, 64, 128, 256 }; int nSizes = sizeof(sizes) / sizeof(int); int w = d_image->w(); int h = d_image->h(); int i, j; for (i=0; i 0 && j > 0) { // Always scale images down in size and reuse the same pixel // memory. This can cause some ugliness... if (w != sizes[i-1] || h != sizes[j-1]) { viewer->scaleTexture( w, h, sizes[i-1], sizes[j-1], d_image->nc(), pix ); d_image->setSize( sizes[i-1], sizes[j-1] ); } d_texObject = viewer->insertTexture(d_image->w(), d_image->h(), d_image->nc(), d_repeatS.get(), d_repeatT.get(), pix, true); } } } clearModified(); } int VrmlNodeImageTexture::nComponents() { return d_image ? d_image->nc() : 0; } int VrmlNodeImageTexture::width() { return d_image ? d_image->w() : 0; } int VrmlNodeImageTexture::height() { return d_image ? d_image->h() : 0; } int VrmlNodeImageTexture::nFrames() { return 0; } unsigned char* VrmlNodeImageTexture::pixels() { return d_image ? d_image->pixels() : 0; } // Set the value of one of the node fields. void VrmlNodeImageTexture::setField(const char *fieldName, const VrmlField &fieldValue) { if (strcmp(fieldName,"url") == 0) { delete d_image; d_image = 0; } if TRY_FIELD(url, MFString) else if TRY_FIELD(repeatS, SFBool) else if TRY_FIELD(repeatT, SFBool) else VrmlNode::setField(fieldName, fieldValue); }