// ------------------------------------------------------------------------------------------------ void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head, unsigned int size ) { ai_assert(!mSurfaces->empty()); LWO::Surface& surf = mSurfaces->back(); LWO::Texture tex; // load the texture header LoadLWO2TextureHeader(head->length,tex); size -= head->length + 6; // now get the exact type of the texture switch (head->type) { case AI_LWO_PROC: LoadLWO2Procedural(size,tex); break; case AI_LWO_GRAD: LoadLWO2Gradient(size,tex); break; case AI_LWO_IMAP: LoadLWO2ImageMap(size,tex); } // get the destination channel TextureList* listRef = NULL; switch (tex.type) { case AI_LWO_COLR: listRef = &surf.mColorTextures;break; case AI_LWO_DIFF: listRef = &surf.mDiffuseTextures;break; case AI_LWO_SPEC: listRef = &surf.mSpecularTextures;break; case AI_LWO_GLOS: listRef = &surf.mGlossinessTextures;break; case AI_LWO_BUMP: listRef = &surf.mBumpTextures;break; case AI_LWO_TRAN: listRef = &surf.mOpacityTextures;break; case AI_LWO_REFL: listRef = &surf.mReflectionTextures;break; default: DefaultLogger::get()->warn("LWO2: Encountered unknown texture type"); return; } // now attach the texture to the parent surface - sort by ordinal string for (TextureList::iterator it = listRef->begin();it != listRef->end(); ++it) { if (::strcmp(tex.ordinal.c_str(),(*it).ordinal.c_str()) < 0) { listRef->insert(it,tex); return; } } listRef->push_back(tex); }
//--------------------------------------------------------------------- void CompositorManager::freePooledTextures(bool onlyIfUnreferenced) { if (onlyIfUnreferenced) { for (TexturesByDef::iterator i = mTexturesByDef.begin(); i != mTexturesByDef.end(); ++i) { TextureList* texList = i->second; for (TextureList::iterator j = texList->begin(); j != texList->end();) { // if the resource system, plus this class, are the only ones to have a reference.. // NOTE: any material references will stop this texture getting freed (e.g. compositor demo) // until this routine is called again after the material no longer references the texture if (j->useCount() == ResourceGroupManager::RESOURCE_SYSTEM_NUM_REFERENCE_COUNTS + 1) { TextureManager::getSingleton().remove((*j)->getHandle()); j = texList->erase(j); } else ++j; } } for (ChainTexturesByDef::iterator i = mChainTexturesByDef.begin(); i != mChainTexturesByDef.end(); ++i) { TextureDefMap& texMap = i->second; for (TextureDefMap::iterator j = texMap.begin(); j != texMap.end();) { const TexturePtr& tex = j->second; if (tex.useCount() == ResourceGroupManager::RESOURCE_SYSTEM_NUM_REFERENCE_COUNTS + 1) { TextureManager::getSingleton().remove(tex->getHandle()); texMap.erase(j++); } else ++j; } } } else { // destroy all for (TexturesByDef::iterator i = mTexturesByDef.begin(); i != mTexturesByDef.end(); ++i) { OGRE_DELETE_T(i->second, TextureList, MEMCATEGORY_GENERAL); } mTexturesByDef.clear(); mChainTexturesByDef.clear(); } }
//--------------------------------------------------------------------- TexturePtr CompositorManager::getPooledTexture(const String& name, const String& localName, size_t w, size_t h, PixelFormat f, uint aa, const String& aaHint, bool srgb, CompositorManager::UniqueTextureSet& texturesAssigned, CompositorInstance* inst, CompositionTechnique::TextureScope scope) { if (scope == CompositionTechnique::TS_GLOBAL) { OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Global scope texture can not be pooled.", "CompositorManager::getPooledTexture"); } TextureDef def(w, h, f, aa, aaHint, srgb); if (scope == CompositionTechnique::TS_CHAIN) { StringPair pair = std::make_pair(inst->getCompositor()->getName(), localName); TextureDefMap& defMap = mChainTexturesByDef[pair]; TextureDefMap::iterator it = defMap.find(def); if (it != defMap.end()) { return it->second; } // ok, we need to create a new one TexturePtr newTex = TextureManager::getSingleton().createManual( name, ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME, TEX_TYPE_2D, (uint)w, (uint)h, 0, f, TU_RENDERTARGET, 0, srgb, aa, aaHint); defMap.insert(TextureDefMap::value_type(def, newTex)); return newTex; } TexturesByDef::iterator i = mTexturesByDef.find(def); if (i == mTexturesByDef.end()) { TextureList* texList = OGRE_NEW_T(TextureList, MEMCATEGORY_GENERAL); i = mTexturesByDef.insert(TexturesByDef::value_type(def, texList)).first; } CompositorInstance* previous = inst->getChain()->getPreviousInstance(inst); CompositorInstance* next = inst->getChain()->getNextInstance(inst); TexturePtr ret; TextureList* texList = i->second; // iterate over the existing textures and check if we can re-use for (TextureList::iterator t = texList->begin(); t != texList->end(); ++t) { TexturePtr& tex = *t; // check not already used if (texturesAssigned.find(tex.get()) == texturesAssigned.end()) { bool allowReuse = true; // ok, we didn't use this one already // however, there is an edge case where if we re-use a texture // which has an 'input previous' pass, and it is chained from another // compositor, we can end up trying to use the same texture for both // so, never allow a texture with an input previous pass to be // shared with its immediate predecessor in the chain if (isInputPreviousTarget(inst, localName)) { // Check whether this is also an input to the output target of previous // can't use CompositorInstance::mPreviousInstance, only set up // during compile if (previous && isInputToOutputTarget(previous, tex)) allowReuse = false; } // now check the other way around since we don't know what order they're bound in if (isInputToOutputTarget(inst, localName)) { if (next && isInputPreviousTarget(next, tex)) allowReuse = false; } if (allowReuse) { ret = tex; break; } } } if (ret.isNull()) { // ok, we need to create a new one ret = TextureManager::getSingleton().createManual( name, ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME, TEX_TYPE_2D, (uint)w, (uint)h, 0, f, TU_RENDERTARGET, 0, srgb, aa, aaHint); texList->push_back(ret); } // record that we used this one in the requester's list texturesAssigned.insert(ret.get()); return ret; }
// ------------------------------------------------------------------------------------------------ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTextureType type) { ai_assert(NULL != pcMat); unsigned int cur = 0, temp = 0; aiString s; bool ret = false; for (TextureList::const_iterator it = in.begin(), end = in.end();it != end;++it) { if (!(*it).enabled || !(*it).bCanUse) continue; ret = true; // Convert lightwave's mapping modes to ours. We let them // as they are, the GenUVcoords step will compute UV // channels if they're not there. aiTextureMapping mapping; switch ((*it).mapMode) { case LWO::Texture::Planar: mapping = aiTextureMapping_PLANE; break; case LWO::Texture::Cylindrical: mapping = aiTextureMapping_CYLINDER; break; case LWO::Texture::Spherical: mapping = aiTextureMapping_SPHERE; break; case LWO::Texture::Cubic: mapping = aiTextureMapping_BOX; break; case LWO::Texture::FrontProjection: DefaultLogger::get()->error("LWO2: Unsupported texture mapping: FrontProjection"); mapping = aiTextureMapping_OTHER; break; case LWO::Texture::UV: { if( UINT_MAX == (*it).mRealUVIndex ) { // We have no UV index for this texture, so we can't display it continue; } // add the UV source index temp = (*it).mRealUVIndex; pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_UVWSRC(type,cur)); mapping = aiTextureMapping_UV; } break; default: ai_assert(false); }; if (mapping != aiTextureMapping_UV) { // Setup the main axis aiVector3D v; switch ((*it).majorAxis) { case Texture::AXIS_X: v = aiVector3D(1.f,0.f,0.f); break; case Texture::AXIS_Y: v = aiVector3D(0.f,1.f,0.f); break; default: // case Texture::AXIS_Z: v = aiVector3D(0.f,0.f,1.f); break; } pcMat->AddProperty(&v,1,AI_MATKEY_TEXMAP_AXIS(type,cur)); // Setup UV scalings for cylindric and spherical projections if (mapping == aiTextureMapping_CYLINDER || mapping == aiTextureMapping_SPHERE) { aiUVTransform trafo; trafo.mScaling.x = (*it).wrapAmountW; trafo.mScaling.y = (*it).wrapAmountH; BOOST_STATIC_ASSERT(sizeof(aiUVTransform)/sizeof(float) == 5); pcMat->AddProperty(&trafo,1,AI_MATKEY_UVTRANSFORM(type,cur)); } DefaultLogger::get()->debug("LWO2: Setting up non-UV mapping"); } // The older LWOB format does not use indirect references to clips. // The file name of a texture is directly specified in the tex chunk. if (mIsLWO2) { // find the corresponding clip (take the last one if multiple // share the same index) ClipList::iterator end = mClips.end(), candidate = end; temp = (*it).mClipIdx; for (ClipList::iterator clip = mClips.begin(); clip != end; ++clip) { if ((*clip).idx == temp) { candidate = clip; } } if (candidate == end) { DefaultLogger::get()->error("LWO2: Clip index is out of bounds"); temp = 0; // fixme: apparently some LWO files shipping with Doom3 don't // have clips at all ... check whether that's true or whether // it's a bug in the loader. s.Set("$texture.png"); //continue; } else { if (Clip::UNSUPPORTED == (*candidate).type) { DefaultLogger::get()->error("LWO2: Clip type is not supported"); continue; } AdjustTexturePath((*candidate).path); s.Set((*candidate).path); // Additional image settings int flags = 0; if ((*candidate).negate) { flags |= aiTextureFlags_Invert; } pcMat->AddProperty(&flags,1,AI_MATKEY_TEXFLAGS(type,cur)); } } else { std::string ss = (*it).mFileName; if (!ss.length()) { DefaultLogger::get()->error("LWOB: Empty file name"); continue; } AdjustTexturePath(ss); s.Set(ss); } pcMat->AddProperty(&s,AI_MATKEY_TEXTURE(type,cur)); // add the blend factor pcMat->AddProperty<float>(&(*it).mStrength,1,AI_MATKEY_TEXBLEND(type,cur)); // add the blend operation switch ((*it).blendType) { case LWO::Texture::Normal: case LWO::Texture::Multiply: temp = (unsigned int)aiTextureOp_Multiply; break; case LWO::Texture::Subtractive: case LWO::Texture::Difference: temp = (unsigned int)aiTextureOp_Subtract; break; case LWO::Texture::Divide: temp = (unsigned int)aiTextureOp_Divide; break; case LWO::Texture::Additive: temp = (unsigned int)aiTextureOp_Add; break; default: temp = (unsigned int)aiTextureOp_Multiply; DefaultLogger::get()->warn("LWO2: Unsupported texture blend mode: alpha or displacement"); } // Setup texture operation pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_TEXOP(type,cur)); // setup the mapping mode pcMat->AddProperty<int>((int*)&mapping,1,AI_MATKEY_MAPPING(type,cur)); // add the u-wrapping temp = (unsigned int)GetMapMode((*it).wrapModeWidth); pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_MAPPINGMODE_U(type,cur)); // add the v-wrapping temp = (unsigned int)GetMapMode((*it).wrapModeHeight); pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_MAPPINGMODE_V(type,cur)); ++cur; } return ret; }