//----------------------------------------------------------------------------------------- QPixmap GenericImageEditorCodec::onBeforeDisplay(Ogre::DataStreamPtr stream) { Ogre::Image image; image.load(stream); ImageConverter imageConverter(image.getWidth(), image.getHeight()); if (mPixmap.convertFromImage(imageConverter.fromOgreImage(image))) return mPixmap; mPixmap = 0; return mPixmap; }
//----------------------------------------------------------------------- void AtlasImageTool::correctAlpha (Ogre::Image& image, Ogre::Real alphaCorrection) { size_t numPixels = image.getWidth() * image.getHeight(); size_t pointer = 0; for (size_t i = 0; i < numPixels; ++i) { Ogre::ColourValue colour; Ogre::PixelUtil::unpackColour(&colour, image.getFormat(), (image.getData() + pointer)); colour.a *= alphaCorrection; Ogre::PixelUtil::packColour(colour, image.getFormat(), (image.getData() + pointer)); pointer += Ogre::PixelUtil::getNumElemBytes(image.getFormat()); } }
void MouseCursor::setSkinType(const Ogre::String type) { mSkinType = type; mDefaultSkinType = type; Ogre::Image i; i.load(mSkinTypeManager->getSkinType("MouseCursor",mSkinType)->getSkinElement(TEXTURE)->getTextureName(),Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); // update cursor size to match texture used setSize(i.getWidth(),i.getHeight()); Sheet* sheet = mMouseCursorDesc.guiManager->getActiveSheet(); if(sheet != NULL) { MouseEventArgs args(sheet); args.position = getPosition(); sheet->fireSheetEvent(SHEET_EVENT_MOUSE_CURSOR_SKIN_CHANGED,args); } }
//----------------------------------------------------------------------- void AtlasImageTool::interpolate (Ogre::Image& interpolatedImage, Ogre::Image& firstImage, Ogre::Image& nextImage, Ogre::Real fraction) { size_t numPixels = interpolatedImage.getWidth() * interpolatedImage.getHeight(); size_t pointer = 0; for (size_t i = 0; i < numPixels; ++i) { Ogre::ColourValue firstColour; Ogre::ColourValue nextColour; Ogre::ColourValue interpolatedColour; Ogre::PixelUtil::unpackColour(&firstColour, firstImage.getFormat(), (firstImage.getData() + pointer)); Ogre::PixelUtil::unpackColour(&nextColour, nextImage.getFormat(), (nextImage.getData() + pointer)); interpolatedColour = firstColour + fraction * (nextColour - firstColour); Ogre::PixelUtil::packColour(interpolatedColour, interpolatedImage.getFormat(), (interpolatedImage.getData() + pointer)); pointer += Ogre::PixelUtil::getNumElemBytes(interpolatedImage.getFormat()); } }
MouseCursor::MouseCursor(const MouseCursorDesc& d) : mSkinType("default"), mDefaultSkinType("default") { mMouseCursorDesc.guiManager = d.guiManager; mSkinTypeManager = SkinTypeManager::getSingletonPtr(); for(int i = 0; i < 4; ++i) mEnteredBorders[i] = false; // Update Size of Cursor to match Skin Texture Ogre::Image i; i.load(mSkinTypeManager->getSkinType("MouseCursor",mSkinType)->getSkinElement(TEXTURE)->getTextureName(),Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); // update cursor size to match texture used setSize(i.getWidth(),i.getHeight()); // Set default position setPosition(0,0); }
void GlobalMap::exploreCell(int cellX, int cellY) { float originX = static_cast<float>((cellX - mMinX) * mCellSize); // NB y + 1, because we want the top left corner, not bottom left where the origin of the cell is float originY = static_cast<float>(mHeight - (cellY + 1 - mMinY) * mCellSize); if (cellX > mMaxX || cellX < mMinX || cellY > mMaxY || cellY < mMinY) return; Ogre::TexturePtr localMapTexture = Ogre::TextureManager::getSingleton().getByName("Cell_" + boost::lexical_cast<std::string>(cellX) + "_" + boost::lexical_cast<std::string>(cellY)); if (!localMapTexture.isNull()) { int mapWidth = localMapTexture->getWidth(); int mapHeight = localMapTexture->getHeight(); mOverlayTexture->load(); mOverlayTexture->getBuffer()->blit(localMapTexture->getBuffer(), Ogre::Image::Box(0,0,mapWidth,mapHeight), Ogre::Image::Box(static_cast<Ogre::uint32>(originX), static_cast<Ogre::uint32>(originY), static_cast<Ogre::uint32>(originX + mCellSize), static_cast<Ogre::uint32>(originY + mCellSize))); Ogre::Image backup; std::vector<Ogre::uchar> data; data.resize(mCellSize*mCellSize*4, 0); backup.loadDynamicImage(&data[0], mCellSize, mCellSize, Ogre::PF_A8B8G8R8); localMapTexture->getBuffer()->blitToMemory(Ogre::Image::Box(0,0,mapWidth,mapHeight), backup.getPixelBox()); for (int x=0; x<mCellSize; ++x) for (int y=0; y<mCellSize; ++y) { assert (originX+x < mOverlayImage.getWidth()); assert (originY+y < mOverlayImage.getHeight()); assert (x < int(backup.getWidth())); assert (y < int(backup.getHeight())); mOverlayImage.setColourAt(backup.getColourAt(x, y, 0), static_cast<size_t>(originX + x), static_cast<size_t>(originY + y), 0); } } }
void BrushSelector::buildPreviewBitmap( const Fairy::TextureInfo texInfo ) { const Ogre::uchar BytePerPixel = 8; // 读取原始image Ogre::Image *oriImage = GetSceneManipulator()->getPreviewImage(texInfo.ownerTextureName); // 源大纹理的大小 size_t oriImageHeight = oriImage->getHeight(); size_t oriImageWidth = oriImage->getWidth(); Ogre::uchar *oriImageData = oriImage->getData(); // 所选纹理的大小 size_t newImageWidth = texInfo.width*TexTileSize; size_t newImageHeight = texInfo.height*TexTileSize; // 分配一个足够大的空间来保存新建的image的数据 size_t newImagegetRowSpan = newImageWidth*oriImage->getBPP()/BytePerPixel; // 新建的image的行宽(单位为字节) Ogre::uchar *newImageData = OGRE_ALLOC_T(Ogre::uchar, oriImageHeight*newImagegetRowSpan, Ogre::MEMCATEGORY_GENERAL);//new Ogre::uchar[newImageHeight*newImagegetRowSpan]; Ogre::uchar *newImageDataPointer = newImageData; // 得知起始像素点 size_t startPoint = ( oriImageWidth * texInfo.topCorner + texInfo.leftCorner ) * TexTileSize * oriImage->getBPP()/BytePerPixel; Ogre::uchar *oriImagedataPointer = oriImageData + startPoint; // 把所选的纹理的数据提取出来,并创建一个新的image for ( Ogre::uint i=0; i<newImageHeight; ++i ) { memcpy(newImageDataPointer, oriImagedataPointer, newImagegetRowSpan); newImageDataPointer += newImagegetRowSpan; oriImagedataPointer += oriImage->getRowSpan(); } Ogre::Image newImage; newImage.loadDynamicImage(newImageData,newImageWidth,newImageHeight,1,oriImage->getFormat(),true); // 如果所选纹理大于64*64,就先resize if ( texInfo.width > 1 || texInfo.height > 1 ) newImage.resize(mPreviewImageWidth, mPreviewImageHeight); // 如果有alpha,要与黑白图进行混合 if ( newImage.getHasAlpha() ) { Ogre::ColourValue col; for ( int i=0; i<mPreviewImageWidth; ++i ) { for ( int j=0; j<mPreviewImageWidth; ++j ) { col = newImage.getColourAt(j,i,0); float alphaValue = col.a; unsigned char r = col.r*255 * alphaValue + mBlackWhitePreviewImage.GetRed(i,j) * ( 1.0f - alphaValue); unsigned char g = col.g*255 * alphaValue + mBlackWhitePreviewImage.GetGreen(i,j) * ( 1.0f - alphaValue); unsigned char b = col.b*255 * alphaValue + mBlackWhitePreviewImage.GetBlue(i,j) * ( 1.0f - alphaValue); // 设置到image中 mCurrentPreviewImage.SetRGB(j,i,r,g,b); } } // 设置到缩略图控件中 mBrushesPreview->SetBitmap(mCurrentPreviewImage); } // 没有alpha,就直接拷贝数据 else { Ogre::ColourValue col; for ( int i=0; i<mPreviewImageWidth; ++i ) { for ( int j=0; j<mPreviewImageWidth; ++j ) { col = newImage.getColourAt(j,i,0); unsigned char r = col.r*255; unsigned char g = col.g*255; unsigned char b = col.b*255; // 设置到image中 mCurrentPreviewImage.SetRGB(j,i,r,g,b); } } mBrushesPreview->SetBitmap(mCurrentPreviewImage); } }
//------------------------------------------------------ void TextureAtlas::build() { if (!mIsDirty) return; bool fitted; size_t area = 0; // build the fonts (if this didn't happen already) // so we'll be sure the glyphs are there to be atlassed FontSet::iterator fit = mMyFonts.begin(); while (fit != mMyFonts.end()) { FontDrawSource* fdsp = *fit++; if (!fdsp->isBuilt()) fdsp->build(); } // First, we sort by size of the DrawSource mMyDrawSources.sort(DrawSourceLess()); // now try to allocate all the draw sources. If we fail, grow and try again do { fitted = true; area = 0; // try to fit DrawSourceList::iterator it = mMyDrawSources.begin(); while (it != mMyDrawSources.end()) { const DrawSourcePtr& ds = *it++; const PixelSize& ps = ds->getPixelSize(); area += ps.getPixelArea(); LOG_VERBOSE("TextureAtlas: (%s) Trying to place %d x %d (%d -> %d)", mAtlasName.c_str(), ps.width, ps.height, ps.getPixelArea(), area); // try to allocate FreeSpaceInfo* fsi = mAtlasAllocation->allocate(ps.width, ps.height); if (fsi) { ds->setPlacementPtr(fsi); } else { fitted = false; break; } } // fitted? if (!fitted) // nope - Enlarge! enlarge(area); } while (!fitted); LOG_INFO("TextureAtlas: (%s) Creating atlas with dimensions %d x %d", mAtlasName.c_str(), mAtlasSize.width, mAtlasSize.height); if (mTexture.isNull()) prepareResources(); // TODO: Reallocate the texture here if needed! Ogre::HardwarePixelBufferSharedPtr pixelBuffer = mTexture->getBuffer(); pixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD); const Ogre::PixelBox& targetBox = pixelBuffer->getCurrentLock(); size_t pixelsize = Ogre::PixelUtil::getNumElemBytes(targetBox.format); size_t rowsize = targetBox.rowPitch * pixelsize; Ogre::uint8* dstData = static_cast<Ogre::uint8*>(targetBox.data); // We'll iterate over all draw sources, painting the pixels onto the allocated space DrawSourceList::iterator it = mMyDrawSources.begin(); while (it != mMyDrawSources.end()) { const DrawSourcePtr& ds = *it++; // render all pixels into the right place FreeSpaceInfo* fsi = reinterpret_cast<FreeSpaceInfo*>(ds->getPlacementPtr()); assert(fsi); // render into the specified place unsigned char* conversionBuf = NULL; const PixelSize& dps = ds->getPixelSize(); Ogre::Image* img = ds->getImage(); Ogre::PixelBox srcPixels = img->getPixelBox(); // convert if the source data don't match if(img->getFormat() != Ogre::PF_BYTE_BGRA) { conversionBuf = new unsigned char[img->getWidth() * img->getHeight() * pixelsize]; Ogre::PixelBox convPixels(Ogre::Box(0, 0, dps.width, dps.height), Ogre::PF_BYTE_BGRA, conversionBuf); Ogre::PixelUtil::bulkPixelConversion(srcPixels, convPixels); srcPixels = convPixels; } size_t srcrowsize = srcPixels.rowPitch * pixelsize; Ogre::uint8* srcData = static_cast<Ogre::uint8*>(srcPixels.data); // TODO: we're always handling 32bit data, so we could as well transfer 4 bytes each iteration instead of one (speedup) for(size_t row = 0; row < dps.height; row++) { for(size_t col = 0; col < srcrowsize; col++) { dstData[((row + fsi->y) * rowsize) + (fsi->x * pixelsize) + col] = srcData[(row * srcrowsize) + col]; } } delete[] conversionBuf; // Convert the full draw source pixel coordinates to the atlas contained ones (initializes the texturing coordinates transform) ds->atlas(mMaterial, fsi->x, fsi->y, mAtlasSize.width, mAtlasSize.height); } // for debug, write the texture to a file /*unsigned char *readrefdata = static_cast<unsigned char*>(targetBox.data); Ogre::Image img; img = img.loadDynamicImage (readrefdata, mTexture->getWidth(), mTexture->getHeight(), mTexture->getFormat()); img.save(mAtlasName + ".png");*/ // and close the pixel buffer of the atlas at the end pixelBuffer->unlock(); mIsDirty = false; }
bool MiniMapMaker::outputTextures(void) { // 如果需要(纹理大小改变了或第一次输出文件时),就重建render texture if (mNeedRecreate) { destroy(); init(); } mTempOutputFileNames.clear(); static const String TEMP_GROUP_NAME = "#TEMP#"; // 创建临时的资源组 Ogre::ResourceGroupManager& rgm = Ogre::ResourceGroupManager::getSingleton(); rgm.addResourceLocation(mPath, "FileSystem", TEMP_GROUP_NAME, false); // 合并所有物体的包围盒 Ogre::AxisAlignedBox aabb; Ogre::SceneManager::MovableObjectIterator itm = mManipulator->getSceneManager()->getMovableObjectIterator(Ogre::EntityFactory::FACTORY_TYPE_NAME); while (itm.hasMoreElements()) { Ogre::MovableObject* movable = itm.getNext(); aabb.merge(movable->getWorldBoundingBox(true)); } mCamera->setFarClipDistance(mCamera->getNearClipDistance() + 2 * (aabb.getMaximum().y - aabb.getMinimum().y )); mCamera->setNearClipDistance(mTileSize/2); // 设置摄像机的高度 Real yPos = mCamera->getNearClipDistance() + aabb.getMaximum().y; TerrainData* terrainData = mManipulator->getTerrainData(); assert (terrainData); float terrainHeight = terrainData->mMaxZ - terrainData->mMinZ; float terrainWidth = terrainData->mMaxX - terrainData->mMinX; // 投影的真正面积 Real projectSize = 0.0f; // 最终切割成小块纹理的块数 int xIndex = 0; int zIndex = 0; Ogre::Vector3 originPoint(Ogre::Vector3::ZERO); if (mUseRealCameraAngle) { float outerSquareWidth = 0.0f; float outerSquareHeight = 0.0f; Ogre::Radian alphaAngle = Ogre::Math::ATan( Ogre::Math::Abs(mMoveZDir.z / mMoveZDir.x) ); switch (mCameraDirQuadrant) { case WestNorth : { float leftWidth = Ogre::Math::Sin(alphaAngle) * terrainHeight; float rightWidth = Ogre::Math::Cos(alphaAngle) * terrainWidth; outerSquareWidth = leftWidth + rightWidth; float topHeight = Ogre::Math::Cos(alphaAngle) * terrainHeight; float bottomHeight = Ogre::Math::Sin(alphaAngle) * terrainWidth; outerSquareHeight = topHeight + bottomHeight; originPoint = Ogre::Vector3(terrainData->mMinX,0,terrainData->mMinZ) + (-mMoveZDir * leftWidth); float projectOffset = yPos / Ogre::Math::Tan(mCamDirAngle); originPoint.x += (mInvertCameraDir * projectOffset ).x; originPoint.z += (mInvertCameraDir * projectOffset ).z; break; } case EastNorth : { float leftWidth = Ogre::Math::Cos(alphaAngle) * terrainWidth; float rightWidth = Ogre::Math::Sin(alphaAngle) * terrainHeight; outerSquareWidth = leftWidth + rightWidth; float topHeight = Ogre::Math::Cos(alphaAngle) * terrainHeight; float bottomHeight = Ogre::Math::Sin(alphaAngle) * terrainWidth; outerSquareHeight = topHeight + bottomHeight; originPoint = Ogre::Vector3(terrainData->mMaxX,0,terrainData->mMinZ) + (-mMoveZDir * leftWidth); float projectOffset = yPos / Ogre::Math::Tan(mCamDirAngle); originPoint.x += (mInvertCameraDir * projectOffset ).x; originPoint.z += (mInvertCameraDir * projectOffset ).z; break; } case EastSouth : { float leftWidth = Ogre::Math::Sin(alphaAngle) * terrainHeight; float rightWidth = Ogre::Math::Cos(alphaAngle) * terrainWidth; outerSquareWidth = leftWidth + rightWidth; float topHeight = Ogre::Math::Sin(alphaAngle) * terrainWidth; float bottomHeight = Ogre::Math::Cos(alphaAngle) * terrainHeight; outerSquareHeight = topHeight + bottomHeight; originPoint = Ogre::Vector3(terrainData->mMaxX,0,terrainData->mMaxZ) + (-mMoveZDir * topHeight); float projectOffset = yPos / Ogre::Math::Tan(mCamDirAngle); originPoint.x += (mInvertCameraDir * projectOffset ).x; originPoint.z += (mInvertCameraDir * projectOffset ).z; break; } case WestSouth : { float leftWidth = Ogre::Math::Sin(alphaAngle) * terrainHeight; float rightWidth = Ogre::Math::Cos(alphaAngle) * terrainWidth; outerSquareWidth = leftWidth + rightWidth; float topHeight = Ogre::Math::Sin(alphaAngle) * terrainWidth; float bottomHeight = Ogre::Math::Cos(alphaAngle) * terrainHeight; outerSquareHeight = topHeight + bottomHeight; originPoint = Ogre::Vector3(terrainData->mMinX,0,terrainData->mMaxZ) + (-mMoveZDir * rightWidth); float projectOffset = yPos / Ogre::Math::Tan(mCamDirAngle); originPoint.x += (mInvertCameraDir * projectOffset ).x; originPoint.z += (mInvertCameraDir * projectOffset ).z; break; } default: { OGRE_EXCEPT(Ogre::Exception::ERR_INTERNAL_ERROR, " wrong camera dir " + Ogre::StringConverter::toString(mCameraDir), "MiniMapMaker::outputTextures"); break; } } // 计算投影的长度 Real factor = Ogre::Math::Sin(mCamDirAngle); if (factor > 0.0f && factor != 1.0f) projectSize = mTileSize / factor; // 根据当前场景的大小,计算需要的分块数 xIndex = Ogre::Math::Ceil( (outerSquareWidth) / mTileSize ) + 1; zIndex = Ogre::Math::Ceil( (outerSquareHeight) / projectSize ) + 1; } else { xIndex = Ogre::Math::Ceil( (terrainData->mMaxX - terrainData->mMinX) / mTileSize ) + 1; zIndex = Ogre::Math::Ceil( (terrainData->mMaxZ - terrainData->mMinZ) / mTileSize ) + 1; originPoint.x = terrainData->mMinX; originPoint.z = terrainData->mMinZ; } // 计算最终的mini map的大小 uint miniMapWidth = xIndex * mTexWidth; uint miniMapHeight = zIndex * mTexHeight; if ( miniMapWidth > 10000 || miniMapHeight > 10000 ) { mLastErrorString = "texture size is out of range!"; return false; } // 创建mini map所需的内存空间 uchar* miniMapData = new uchar[miniMapWidth * miniMapHeight * Ogre::PixelUtil::getNumElemBytes(mOutPutFormat)]; //// 初始的摄像机位置 Real xPos = originPoint.x; Real zPos = originPoint.z; for ( int i=0; i<xIndex; ++i ) { for ( int j=0; j<zIndex; ++j ) { // 设置摄像机位置,并更新render texture的内容 mCamera->setPosition(xPos, yPos, zPos); mRenderTexture->update(); String fileName = mPath + mSceneBaseName + Ogre::StringConverter::toString(i) + "_" + Ogre::StringConverter::toString(j) + "." + mTexExtension; // 输出小纹理文件 mRenderTexture->writeContentsToFile(fileName); mTempOutputFileNames.push_back(fileName); // 读取刚创建的纹理 Ogre::Image* tempImage = new Ogre::Image; tempImage->load(mSceneBaseName + Ogre::StringConverter::toString(i) + "_" + Ogre::StringConverter::toString(j) + "." + mTexExtension, TEMP_GROUP_NAME); // 获取render texture中的内容 uchar* tempImageData = tempImage->getData(); // 定位在mini map中的左上角 uint miniMapIndex = ( j * mTexHeight * miniMapWidth + i * mTexWidth ) * Ogre::PixelUtil::getNumElemBytes(mOutPutFormat); uchar* startData = miniMapData + miniMapIndex; for ( size_t height = 0; height < tempImage->getHeight(); ++height ) { for ( size_t width = 0; width < tempImage->getWidth(); ++width ) { memcpy(startData, tempImageData, Ogre::PixelUtil::getNumElemBytes(mOutPutFormat)); startData += Ogre::PixelUtil::getNumElemBytes(mOutPutFormat); tempImageData += Ogre::PixelUtil::getNumElemBytes( tempImage->getFormat() ); } startData += (miniMapWidth - tempImage->getWidth()) * Ogre::PixelUtil::getNumElemBytes(mOutPutFormat); } delete tempImage; // 移动摄像机的z坐标 if (mUseRealCameraAngle) { zPos += (mInvertCameraDir * (projectSize)).z; xPos += (mInvertCameraDir * (projectSize)).x; } else zPos += mTileSize; } if (mUseRealCameraAngle) { xPos = originPoint.x; zPos = originPoint.z; xPos += (mMoveZDir * (mTileSize) * (i+1)).x; zPos += (mMoveZDir * (mTileSize) * (i+1)).z; } else { // 操作完每一列之后,重置摄像机的z坐标 zPos = terrainData->mMinZ; // 移动摄像机的x坐标 xPos += mTileSize; } } // 保存mini map并输出 Ogre::Image* miniMapImage = new Ogre::Image; miniMapImage->loadDynamicImage(miniMapData, miniMapWidth, miniMapHeight, 1, mOutPutFormat, true); miniMapImage->save(mPath + mOutFileName + "." + mTexExtension); delete miniMapImage; rgm.destroyResourceGroup(TEMP_GROUP_NAME); return true; }
Vector4* SnowTerrain::getTerrainNormalData() { PixelBox* terrainNormals; // load from normals file if(mSnowConfig->terrainSettings.normalsDataFile.length() > 0) { // get terrain normal data using image Ogre::Image img; img.load(mSnowConfig->terrainSettings.normalsDataFile, "General"); //img.flipAroundY(); //img.flipAroundX(); size_t size = img.getWidth(); assert(img.getWidth() == img.getHeight()); if (img.getWidth() != mTerrainSize || img.getHeight() != mTerrainSize) img.resize(mTerrainSize, mTerrainSize); terrainNormals = &img.getPixelBox(); Vector4* floats = convertNormalsToFloats(terrainNormals, true); //OGRE_FREE(terrainNormals->data, Ogre::MEMCATEGORY_GENERAL); // need to swap z and y vector due to different vertical axis in normal map and world space! for(size_t i = 0;i<mTerrainSize*mTerrainSize;i++) { Vector4 v = floats[i]; floats[i].z = v.y; floats[i].y = v.z; } return floats; } else { // need to wait until terrain is loaded while (getTerrain()->isDerivedDataUpdateInProgress()) { // we need to wait for this to finish OGRE_THREAD_SLEEP(50); Root::getSingleton().getWorkQueue()->processResponses(); } // Get terrain normal data using official method //terrainNormals = getTerrain()->calculateNormals(Ogre::Rect(0,0,mTerrainSize,mTerrainSize),Rect(0,0,mTerrainSize,mTerrainSize)); Ogre::Image img; getTerrain()->getTerrainNormalMap()->convertToImage(img); //img.flipAroundY(); img.flipAroundX(); //img.save("test_normals.bmp"); terrainNormals = &img.getPixelBox(); Vector4* floats = convertNormalsToFloats(terrainNormals, true); //OGRE_FREE(terrainNormals->data, Ogre::MEMCATEGORY_GENERAL); return floats; } }
AssetLoadState TextureAsset::DeserializeFromData(const u8 *data, size_t numBytes) { if (!data) return ASSET_LOAD_FAILED; ///\todo Log out error. if (numBytes == 0) return ASSET_LOAD_FAILED; ///\todo Log out error. // Don't load textures to memory in headless mode if (assetAPI->IsHeadless()) { return ASSET_LOAD_FAILED; } if (OGRE_THREAD_SUPPORT != 0) { // We can only do threaded loading from disk, and not any disk location but only from asset cache. // local:// refs will return empty string here and those will fall back to the non-threaded loading. // Do not change this to do DiskCache() as that directory for local:// refs will not be a known resource location for ogre. QString cacheDiskSource = assetAPI->GetAssetCache()->GetDiskSource(QUrl(Name())); if (!cacheDiskSource.isEmpty()) { QFileInfo fileInfo(cacheDiskSource); std::string sanitatedAssetRef = fileInfo.fileName().toStdString(); loadTicket_ = Ogre::ResourceBackgroundQueue::getSingleton().load(Ogre::TextureManager::getSingleton().getResourceType(), sanitatedAssetRef, OgreRenderer::OgreRenderingModule::CACHE_RESOURCE_GROUP, false, 0, 0, this); return ASSET_LOAD_PROCESSING; } } try { // Convert the data into Ogre's own DataStream format. std::vector<u8> tempData(data, data + numBytes); #include "DisableMemoryLeakCheck.h" Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream(&tempData[0], tempData.size(), false)); #include "EnableMemoryLeakCheck.h" // Load up the image as an Ogre CPU image object. Ogre::Image image; image.load(stream); if (ogreTexture.isNull()) // If we are creating this texture for the first time, create a new Ogre::Texture object. { ogreAssetName = OgreRenderer::SanitateAssetIdForOgre(this->Name().toStdString()).c_str(); ogreTexture = Ogre::TextureManager::getSingleton().loadImage(ogreAssetName.toStdString(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, image); } else // If we're loading on top of an Ogre::Texture we've created before, don't lose the old Ogre::Texture object, but reuse the old. { // This will allow all existing materials to keep referring to this texture, and they'll get the updated texture image immediately. ogreTexture->freeInternalResources(); if (image.getWidth() != ogreTexture->getWidth() || image.getHeight() != ogreTexture->getHeight() || image.getFormat() != ogreTexture->getFormat()) { ogreTexture->setWidth(image.getWidth()); ogreTexture->setHeight(image.getHeight()); ogreTexture->setFormat(image.getFormat()); } if (ogreTexture->getBuffer().isNull()) { LogError("DeserializeFromData: Failed to create texture " + this->Name().toStdString() + ": OgreTexture::getBuffer() was null!"); return ASSET_LOAD_FAILED; } Ogre::PixelBox pixelBox(Ogre::Box(0,0, image.getWidth(), image.getHeight()), image.getFormat(), (void*)image.getData()); ogreTexture->getBuffer()->blitFromMemory(pixelBox); ogreTexture->createInternalResources(); } return ASSET_LOAD_SUCCESFULL; } catch (Ogre::Exception &e) { LogError("DeserializeFromData: Failed to create texture " + this->Name().toStdString() + ": " + std::string(e.what())); return ASSET_LOAD_FAILED; } }
/* ----------------------------------------------------------------------- | build bullet height field shape and generate ogre mesh from grayscale image | | @param in : | @param out: raw data of height field terrain | ToDo: adjest grid scale, grid height, local scale, max/min height ----------------------------------------------------------------------- */ bool buildHeightFieldTerrainFromImage(const Ogre::String& filename, btDynamicsWorld* dynamicsWorld, btAlignedObjectArray<btCollisionShape*>& collisionShapes, void* &data) { Ogre::Image img; try { img.load(filename, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); } catch(Ogre::Exception err) { LOG(err.what()); return false; } size_t grid_w = 65, grid_h = 65; // must be (2^N) + 1 size_t grid_max_w = 129, grid_max_h = 129; // must be (2^N) + 1 size_t img_w = img.getWidth(); size_t img_h = img.getHeight(); // validate image size is (2^N) + 1 if ((img_w-1) & (img_w-2)) img_w = grid_w; if ((img_h-1) & (img_h-2)) img_h = grid_h; //if (img_w > grid_max_w) img_w = grid_max_w; //if (img_h > grid_max_h) img_h = grid_max_h; LOG("LoadImage name=%s, width=%d, height=%d, width^2+1=%d, height^2+1=%d", filename.c_str(), img.getWidth(), img.getHeight(), img_w, img_h); img.resize(img_w, img_h); size_t pixelSize = Ogre::PixelUtil::getNumElemBytes(img.getFormat()); size_t bufSize = img.getSize() / pixelSize; data = new Ogre::Real[ bufSize ]; Ogre::Real* dest = static_cast<Ogre::Real*>(data); memset(dest, 0, bufSize); /* | @ Notice the alignment problem | - uchar to float alignment | - pixel format in bytes as rawdata type, also affects alignment */ Ogre::uchar* src = img.getData(); for (size_t i=0;i<bufSize;++i) { dest[i] = ((Ogre::Real)src[i * pixelSize] - 127.0f)/16.0f; } // parameter int upAxis = 1; btScalar gridSpacing = 5.0f; btScalar gridHeightScale = 0.2f; btScalar minHeight = -10.0f; btScalar maxHeight = 10.0f; btScalar defaultContactProcessingThreshold = BT_LARGE_FLOAT; btHeightfieldTerrainShape *heightfieldShape = new btHeightfieldTerrainShape(img_w, img_h, dest, gridHeightScale, minHeight, maxHeight, upAxis, PHY_FLOAT, false); btAssert(heightfieldShape && "null heightfield"); // shape btVector3 localScaling(1.0f, 1.0f, 1.0f); heightfieldShape->setLocalScaling(localScaling); collisionShapes.push_back(heightfieldShape); // rigidBody btDefaultMotionState* motionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,0,0))); btRigidBody::btRigidBodyConstructionInfo cInfo(0, motionState, heightfieldShape, btVector3(0,0,0)); btRigidBody* rigidBody = new btRigidBody(cInfo); rigidBody->setContactProcessingThreshold(defaultContactProcessingThreshold); int flags = rigidBody->getCollisionFlags(); rigidBody->setCollisionFlags(flags | btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT); dynamicsWorld->addRigidBody(rigidBody); // add ogre height field mesh Ogre::SceneManager* sceneMgr = Ogre::Root::getSingletonPtr()->getSceneManager("DefaultSceneManager"); btAssert(sceneMgr); Ogre::ManualObject* obj = sceneMgr->createManualObject("btHeightFieldEntity"); btVector3 aabbMin, aabbMax; heightfieldShape->getAabb(btTransform(btQuaternion(0,0,0,1),btVector3(0,0,0)), aabbMin, aabbMax); btHeightFieldProcessor callback(obj, "DefaultPlane"); heightfieldShape->processAllTriangles(&callback, aabbMin, aabbMax); sceneMgr->getRootSceneNode()->attachObject(obj); return true; }
void BrushSelector::OnPixmapListSelected(wxTreeEvent& event) { try { // 以下是改成定义文件后的修改 // mPaintInOneGrid = false; // 保存当前选中的纹理的大小 int selectedTexXSize = 0; int selectedTexZSize = 0; // 当画刷被选中时,要进行判断 wxTreeItemId itemId = event.GetItem(); wxTreeItemId rootId = mBrushesTree->GetRootItem(); // 如果选中根,就返回 if ( itemId == rootId ) { // 选中根目录名时,所有选项都变灰 mFlipHorizontal->Enable(false); mFlipVertical->Enable(false); mRotateRightAngle->Enable(false); mMirrorDiagonal->Enable(false); mRandom->Enable(false); mEnablePreview->Enable(false); // 缩略图用黑白图 mBrushesPreview->SetBitmap(mBlackWhitePreviewImage); return; } if (itemId.IsOk()) { mCurrentOrientationType = 0; // 如果选项的父是root,说明该画刷是放在根目录下的,也有可能是根目录下的子目录 if ( mBrushesTree->GetItemParent(itemId) == rootId ) { mCurrentFileName = mBrushesTree->GetItemText(itemId); } else { // 以下处理不是放在根目录下的画刷 wxTreeItemId parentId = mBrushesTree->GetItemParent(itemId); mCurrentFileName = mBrushesTree->GetItemText(itemId); // 以此取出父目录的目录名,组合成相对路径名,并加上文件名 while ( parentId != rootId ) { wxString parentText = mBrushesTree->GetItemText(parentId); parentText += '/'; mCurrentFileName.Prepend( parentText ); parentId = mBrushesTree->GetItemParent(parentId); } } // 如果名字中有.,说明是文件名,不是目录名 if ( mCurrentFileName.find_first_of('|') != wxString::npos ) { mFlipHorizontal->Enable(true); mFlipVertical->Enable(true); mRotateRightAngle->Enable(true); mMirrorDiagonal->Enable(true); mRandom->Enable(true); mEnablePreview->Enable(true); Ogre::String currentFileName(mCurrentFileName.c_str()); size_t pos = currentFileName.find_last_of('/'); // 取出brush名称 Ogre::String brushName = currentFileName.substr(0,pos); Ogre::String textureName = currentFileName.substr(pos+1); const Fairy::TextureInfos ¤tPaintInfos = GetSceneManipulator()->getTextureInfos(brushName); const Fairy::TextureInfo ¤tPaintInfo = GetSceneManipulator()->getTextureInfo(brushName, textureName); Ogre::Image *previewImage = GetSceneManipulator()->getPreviewImage(currentPaintInfo.ownerTextureName); // 组成纹理信息字符串 Ogre::String texInfoString; texInfoString += currentPaintInfo.ownerTextureName; texInfoString += "|"; texInfoString += Ogre::StringConverter::toString(currentPaintInfo.height); texInfoString += "|"; texInfoString += Ogre::StringConverter::toString(currentPaintInfo.width); texInfoString += "|"; texInfoString += Ogre::StringConverter::toString(currentPaintInfo.leftCorner); texInfoString += "|"; texInfoString += Ogre::StringConverter::toString(currentPaintInfo.topCorner); texInfoString += "|"; texInfoString += Ogre::StringConverter::toString(previewImage->getHeight()); texInfoString += "|"; texInfoString += Ogre::StringConverter::toString(previewImage->getWidth()); texInfoString += "|"; texInfoString += Ogre::StringConverter::toString(currentPaintInfo.rotateType); Fairy::Action* action = GetSceneManipulator()->_getAction("SimplePaintAction"); action->setParameter( "%TextureName", "InputBegin" ); action->setParameter( "%TextureName", AS_STRING(texInfoString) ); action->setParameter( "%OrientationType", Ogre::StringConverter::toString(mCurrentOrientationType) ); if ( (currentPaintInfo.width > 1 || currentPaintInfo.height > 1) && !mPaintInOneGrid ) { action->setParameter( "%TexNormalSize", "false" ); mFlipHorizontal->Enable(false); mFlipVertical->Enable(false); mRotateRightAngle->Enable(false); mMirrorDiagonal->Enable(false); mRandom->Enable(false); } else { action->setParameter("%TexNormalSize","true"); } GetSceneManipulator()->setActiveAction(action); buildPreviewBitmap(currentPaintInfo); if ( mEnablePreview->IsChecked() == false ) { // 如果不显示缩略图,就显示默认的黑白图 mBrushesPreview->SetBitmap(mBlackWhitePreviewImage); } } // 如果名字中有.,说明不是文件名,是目录名 else { mFlipHorizontal->Enable(false); mFlipVertical->Enable(false); mRotateRightAngle->Enable(false); mMirrorDiagonal->Enable(false); mRandom->Enable(false); mEnablePreview->Enable(true); // 把整个目录的纹理进行判断,并加入到透明纹理列表 const Fairy::Action* action = OnStartAutoTexAction(itemId, mCurrentFileName); if ( action != 0 ) { // 从该组纹理的实心纹理中随机用一个来做为缩略图 // 读取这张纹理,并缩放到mPreviewImageWidth*mPreviewImageHeight,用于缩略图 // Ogre::String tempTexName = action->getParameter( "%TextureName" ); const Fairy::TextureInfos ¤tPaintInfos = GetSceneManipulator()->getTextureInfos(mCurrentFileName.c_str()); // const Fairy::TextureInfo ¤tPaintInfo = currentPaintInfos[0]; // 构建preview image buildPreviewBitmap(currentPaintInfos[0]); } else { mEnablePreview->Enable(false); mBrushesPreview->SetBitmap(mBlackWhitePreviewImage); } if ( mEnablePreview->IsChecked() == false ) { // 如果不显示缩略图,就显示默认的黑白图 mBrushesPreview->SetBitmap(mBlackWhitePreviewImage); } } } // 让所有的checkbox回复未选择的状态 mFlipHorizontal->SetValue(false); mFlipVertical->SetValue(false); mRotateRightAngle->SetValue(false); mMirrorDiagonal->SetValue(false); mRandom->SetValue(false); } catch (Ogre::Exception &e) { wxMessageBox( e.getDescription().c_str(), /* _("Texture Wrong")*/wxT("纹理定义出错或找不到纹理图片"), wxOK|wxCENTRE|wxICON_ERROR, this); } }
void Terrain::_createAtlasPixmap(size_t pixmapId) { const TerrainData::Pixmap& pixmap = mData->mPixmaps[pixmapId]; size_t textureId = pixmap.textureId; assert(textureId < mData->mTextures.size()); const Ogre::String& textureName = mData->mTextures[textureId]; // If the atlas texture already exist, use it. AtlasArray::const_iterator it; for (it = mAtlases.begin(); it != mAtlases.end(); ++it) { if (it->texture->getName() == textureName) break; } if (it != mAtlases.end()) { // Fill up atlas pixmap info size_t atlasId = it - mAtlases.begin() + 1; mAtlasPixmaps[pixmapId].atlasId = atlasId; mAtlasPixmaps[pixmapId].left = pixmap.left; mAtlasPixmaps[pixmapId].top = pixmap.top; mAtlasPixmaps[pixmapId].right = pixmap.right; mAtlasPixmaps[pixmapId].bottom = pixmap.bottom; return; } // If texture already loaded and is composited, use it without any modify. Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().getByName(textureName); if (!texture.isNull() && (texture->getWidth() > mAtlasPixmapSize || texture->getHeight() > mAtlasPixmapSize)) { mAtlases.push_back(Atlas()); Atlas& atlas = mAtlases.back(); atlas.texture = texture; // Fill up atlas pixmap info size_t atlasId = mAtlases.size(); mAtlasPixmaps[pixmapId].atlasId = atlasId; mAtlasPixmaps[pixmapId].left = pixmap.left; mAtlasPixmaps[pixmapId].top = pixmap.top; mAtlasPixmaps[pixmapId].right = pixmap.right; mAtlasPixmaps[pixmapId].bottom = pixmap.bottom; return; } // Load the image Ogre::Image image; image.load(textureName, BRUSH_RESOURCE_GROUP_NAME); // If the image is composited, use it without any modify. if (image.getWidth() > mAtlasPixmapSize || image.getHeight() > mAtlasPixmapSize) { mAtlases.push_back(Atlas()); Atlas& atlas = mAtlases.back(); // re-use the loaded image avoid load it again atlas.texture = Ogre::TextureManager::getSingleton() .loadImage(textureName, BRUSH_RESOURCE_GROUP_NAME, image); // Fill up atlas pixmap info size_t atlasId = mAtlases.size(); mAtlasPixmaps[pixmapId].atlasId = atlasId; mAtlasPixmaps[pixmapId].left = pixmap.left; mAtlasPixmaps[pixmapId].top = pixmap.top; mAtlasPixmaps[pixmapId].right = pixmap.right; mAtlasPixmaps[pixmapId].bottom = pixmap.bottom; return; } // Composite into the atlas texture. bool isTransparent = image.getHasAlpha(); AtlasAllocInfo& allocInfo = isTransparent ? mTransparentAtlasAllocInfo : mSolidAtlasAllocInfo; if (allocInfo.blockId >= mMaxAtlasBlockId) { // Use special name to avoid confuse with other reference with this texture Ogre::String atlasName = "<Terrain/Atlas>:" + Ogre::StringConverter::toString(mAtlases.size()); mAtlases.push_back(Atlas()); Atlas& atlas = mAtlases.back(); Ogre::PixelFormat pixelFormat = isTransparent ? Ogre::PF_A8R8G8B8 : Ogre::PF_X8R8G8B8; atlas.image.bind(new Ogre::Image); atlas.image->loadDynamicImage(0, mAtlasTextureSize, mAtlasTextureSize, 1, pixelFormat, true, 1, mAtlasNumMipMaps); memset(atlas.image->getData(), 0, atlas.image->getSize()); atlas.texture = Ogre::TextureManager::getSingleton().createManual(atlasName, BRUSH_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, atlas.image->getWidth(), atlas.image->getHeight(), mAtlasNumMipMaps, atlas.image->getFormat(), Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE, this); allocInfo.atlasId = mAtlases.size(); allocInfo.blockId = 0; } // Copy origin pixmap to atlas image Atlas& atlas = mAtlases[allocInfo.atlasId - 1]; int blockX = allocInfo.blockId % mAtlasBlockSize; int blockY = allocInfo.blockId / mAtlasBlockSize; Ogre::PixelBox dst = atlas.image->getPixelBox().getSubVolume(Ogre::Box( blockX * mAtlasPixmapSize, blockY * mAtlasPixmapSize, blockX * mAtlasPixmapSize + mAtlasPixmapSize, blockY * mAtlasPixmapSize + mAtlasPixmapSize)); Ogre::PixelBox src = image.getPixelBox().getSubVolume(Ogre::Box( fast_ifloor(pixmap.left * image.getWidth() + 0.5f), fast_ifloor(pixmap.top * image.getHeight() + 0.5f), fast_ifloor(pixmap.right * image.getWidth() + 0.5f), fast_ifloor(pixmap.bottom * image.getHeight() + 0.5f))); if (src.getWidth() == mAtlasPixmapSize && src.getHeight() == mAtlasPixmapSize) Ogre::PixelUtil::bulkPixelConversion(src, dst); else Ogre::Image::scale(src, dst); // Generate mipmaps manual for (size_t mipmap = 1; mipmap <= mAtlasNumMipMaps; ++mipmap) { src = dst; size_t pixmapSize = mAtlasPixmapSize >> mipmap; dst = atlas.image->getPixelBox(0, mipmap).getSubVolume(Ogre::Box( blockX * pixmapSize, blockY * pixmapSize, blockX * pixmapSize + pixmapSize, blockY * pixmapSize + pixmapSize)); Ogre::Image::scale(src, dst); } // Notify that the atlas texture need to reload if (atlas.texture->isLoaded()) atlas.texture->unload(); ++allocInfo.blockId; // Fill up atlas pixmap info mAtlasPixmaps[pixmapId].atlasId = allocInfo.atlasId; mAtlasPixmaps[pixmapId].left = blockX * mAtlasBlockTexCoordInc + 0.5f / mAtlasTextureSize; mAtlasPixmaps[pixmapId].top = blockY * mAtlasBlockTexCoordInc + 0.5f / mAtlasTextureSize; mAtlasPixmaps[pixmapId].right = mAtlasPixmaps[pixmapId].left + mAtlasBlockTexCoordInc - 1.0f / mAtlasTextureSize; mAtlasPixmaps[pixmapId].bottom = mAtlasPixmaps[pixmapId].top + mAtlasBlockTexCoordInc - 1.0f / mAtlasTextureSize; }
void SaveGameDialog::onSlotSelected(MyGUI::ListBox *sender, size_t pos) { if (pos == MyGUI::ITEM_NONE) { mCurrentSlot = NULL; mInfoText->setCaption(""); mScreenshot->setImageTexture(""); return; } if (mSaving) mSaveNameEdit->setCaption(sender->getItemNameAt(pos)); mCurrentSlot = NULL; unsigned int i=0; for (MWState::Character::SlotIterator it = mCurrentCharacter->begin(); it != mCurrentCharacter->end(); ++it, ++i) { if (i == pos) mCurrentSlot = &*it; } assert(mCurrentSlot && "Can't find selected slot"); std::stringstream text; time_t time = mCurrentSlot->mTimeStamp; struct tm* timeinfo; timeinfo = localtime(&time); // Use system/environment locale settings for datetime formatting setlocale(LC_TIME, ""); const int size=1024; char buffer[size]; if (std::strftime(buffer, size, "%x %X", timeinfo) > 0) text << buffer << "\n"; text << "Level " << mCurrentSlot->mProfile.mPlayerLevel << "\n"; text << mCurrentSlot->mProfile.mPlayerCell << "\n"; // text << "Time played: " << slot->mProfile.mTimePlayed << "\n"; int hour = int(mCurrentSlot->mProfile.mInGameTime.mGameHour); bool pm = hour >= 12; if (hour >= 13) hour -= 12; if (hour == 0) hour = 12; text << mCurrentSlot->mProfile.mInGameTime.mDay << " " << MWBase::Environment::get().getWorld()->getMonthName(mCurrentSlot->mProfile.mInGameTime.mMonth) << " " << hour << " " << (pm ? "#{sSaveMenuHelp05}" : "#{sSaveMenuHelp04}"); mInfoText->setCaptionWithReplacing(text.str()); // Decode screenshot std::vector<char> data = mCurrentSlot->mProfile.mScreenshot; // MemoryDataStream doesn't work with const data :( Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream(&data[0], data.size())); Ogre::Image image; image.load(stream, "jpg"); const std::string textureName = "@savegame_screenshot"; Ogre::TexturePtr texture; texture = Ogre::TextureManager::getSingleton().getByName(textureName); mScreenshot->setImageTexture(""); if (texture.isNull()) { texture = Ogre::TextureManager::getSingleton().createManual(textureName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, image.getWidth(), image.getHeight(), 0, Ogre::PF_BYTE_RGBA, Ogre::TU_DYNAMIC_WRITE_ONLY); } texture->unload(); texture->setWidth(image.getWidth()); texture->setHeight(image.getHeight()); texture->loadImage(image); mScreenshot->setImageTexture(textureName); }
void MaterialPreviewDialog::buildPreviewBitmap( const Ogre::String &texName ) { const Ogre::uchar BytePerPixel = 8; // 读取原始image Ogre::Image *oriImage = getPreviewImage(texName); // 源大纹理的大小 size_t oriImageHeight = oriImage->getHeight(); size_t oriImageWidth = oriImage->getWidth(); Ogre::uchar *oriImageData = oriImage->getData(); // 分配一个足够大的空间来保存新建的image的数据 size_t newImagegetRowSpan = oriImageWidth*oriImage->getBPP()/BytePerPixel; // 新建的image的行宽(单位为字节) Ogre::uchar *newImageData = new Ogre::uchar[oriImageHeight*newImagegetRowSpan]; Ogre::uchar *newImageDataPointer = newImageData; Ogre::uchar *oriImagedataPointer = oriImageData; // 把所选的纹理的数据提取出来,并创建一个新的image for ( Ogre::uint i=0; i<oriImageHeight; ++i ) { memcpy(newImageDataPointer, oriImagedataPointer, newImagegetRowSpan); newImageDataPointer += newImagegetRowSpan; oriImagedataPointer += oriImage->getRowSpan(); } Ogre::Image newImage; newImage.loadDynamicImage(newImageData,oriImageWidth,oriImageHeight,1,oriImage->getFormat(),true); // 如果所选纹理大于64*64,就先resize if ( oriImageWidth > mPreviewImageWidth || oriImageHeight > mPreviewImageHeight ) newImage.resize(mPreviewImageWidth, mPreviewImageHeight); // 如果有alpha,要与黑白图进行混合 if ( newImage.getHasAlpha() ) { Ogre::uchar *tempPtr = newImage.getData(); assert (tempPtr); for ( size_t i=0; i<mPreviewImageHeight; ++i ) for ( size_t j=0; j<mPreviewImageWidth; ++j ) { // 取出alpha值 float alphaValue = (float)tempPtr[3] / 255.0f; // 计算出经过alpha混合后的颜色值 unsigned char r = tempPtr[2] * alphaValue; unsigned char g = tempPtr[1] * alphaValue; unsigned char b = tempPtr[0] * alphaValue; // 设置到image中 mCurrentPreviewImage.SetRGB(j,i,r,g,b); tempPtr += 4; } // 要把指针移回到图片数据的 tempPtr -= mPreviewImageHeight * mPreviewImageWidth * 4; // 设置到缩略图控件中 } // 没有alpha,就直接拷贝数据 else { memcpy ( mCurrentPreviewImage.GetData(), newImage.getData(), newImage.getSize() ); } }
// ---------------------------------------------------------------------- void FontSerializer::exportFont(const Font *pFont, const Ogre::String &fileName) { // Open/create the file mpfFile = fopen(fileName.c_str(), "wb"); if (!mpfFile) { // Throw an error if the file was not found, or was not possible to read SONETTO_THROW("A file was not found!"); } fwrite(&Font::mFourCC, sizeof(uint32), 1, mpfFile); fwrite(&pFont->mVersion, sizeof(uint32), 1, mpfFile); fwrite(&pFont->mEncode, sizeof(uint32), 1, mpfFile); fwrite(&pFont->mVerticalOffsetTop, sizeof(float), 1, mpfFile); fwrite(&pFont->mVerticalOffsetBottom, sizeof(float), 1, mpfFile); fwrite(&pFont->mHorizontalScale, sizeof(float), 1, mpfFile); saveString(pFont->mIName); if(pFont->mMaterial.isNull()) SONETTO_THROW("Material does not exist"); Ogre::Pass * pass = pFont->mMaterial->getTechnique(0)->getPass(0); bool has_separate_blend = pass->hasSeparateSceneBlending(); uint32 mat_scene_blend_source = (uint32)pass->getSourceBlendFactor(); uint32 mat_scene_blend_dest = (uint32)pass->getDestBlendFactor(); uint32 mat_scene_blend_source_a = (uint32)pass->getSourceBlendFactorAlpha(); uint32 mat_scene_blend_dest_a = (uint32)pass->getDestBlendFactorAlpha(); fwrite(&has_separate_blend, sizeof(bool), 1, mpfFile); fwrite(&mat_scene_blend_source, sizeof(uint32), 1, mpfFile); fwrite(&mat_scene_blend_dest, sizeof(uint32), 1, mpfFile); fwrite(&mat_scene_blend_source_a, sizeof(uint32), 1, mpfFile); fwrite(&mat_scene_blend_dest_a, sizeof(uint32), 1, mpfFile); uint32 mat_alpha_reject_func = (uint32)pass->getAlphaRejectFunction(); uint8 mat_alpha_reject_val = (uint8)pass->getAlphaRejectValue(); bool map_alpha_reject_atc = pass->isAlphaToCoverageEnabled(); fwrite(&mat_alpha_reject_func, sizeof(uint32), 1, mpfFile); fwrite(&mat_alpha_reject_val, sizeof(uint8), 1, mpfFile); fwrite(&map_alpha_reject_atc, sizeof(bool), 1, mpfFile); Ogre::TextureUnitState * texunit = pass->getTextureUnitState(0); Ogre::TextureUnitState::UVWAddressingMode tex_address_mode_uvw = texunit->getTextureAddressingMode(); uint32 tex_address_mode_u = (uint32)tex_address_mode_uvw.u; uint32 tex_address_mode_v = (uint32)tex_address_mode_uvw.v; uint32 tex_address_mode_w = (uint32)tex_address_mode_uvw.w; uint32 tex_filtering_min = (uint32)texunit->getTextureFiltering(Ogre::FT_MIN); uint32 tex_filtering_mag = (uint32)texunit->getTextureFiltering(Ogre::FT_MAG); Ogre::ColourValue tex_border_color = texunit->getTextureBorderColour(); fwrite(&tex_address_mode_u,sizeof(uint32), 1, mpfFile); fwrite(&tex_address_mode_v,sizeof(uint32), 1, mpfFile); fwrite(&tex_address_mode_w,sizeof(uint32), 1, mpfFile); fwrite(&tex_filtering_min,sizeof(uint32), 1, mpfFile); fwrite(&tex_filtering_mag,sizeof(uint32), 1, mpfFile); fwrite(tex_border_color.ptr(),sizeof(float)*4, 1, mpfFile); uint32 colsize = (uint32)pFont->mColorList.size(); fwrite(&colsize,sizeof(uint32), 1, mpfFile); for(uint32 i = 0; i != colsize; ++i) { fwrite(pFont->mColorList[i].ptr(),sizeof(float)*4, 1, mpfFile); } for(uint32 i = 0; i != 256; ++i) { FontGlyph glyph = pFont->mGlyph[i]; fwrite(&glyph, sizeof(FontGlyph), 1,mpfFile); } Ogre::Image * tex = pFont->mFontImage; size_t uWidth = tex->getWidth(); size_t uHeight = tex->getHeight(); size_t uDepth = tex->getDepth(); size_t eFormat = (uint32)tex->getFormat(); size_t numFaces = tex->getNumFaces(); size_t numMipMaps = tex->getNumMipmaps(); fwrite(&uWidth, sizeof(size_t), 1, mpfFile); fwrite(&uHeight, sizeof(size_t), 1, mpfFile); fwrite(&uDepth, sizeof(size_t), 1, mpfFile); fwrite(&eFormat, sizeof(size_t), 1, mpfFile); fwrite(&numFaces, sizeof(size_t), 1, mpfFile); fwrite(&numMipMaps, sizeof(size_t), 1, mpfFile); size_t texdatasize = Ogre::Image::calculateSize(numMipMaps, numFaces, uWidth, uHeight, uDepth, (Ogre::PixelFormat)eFormat); fwrite(tex->getData(),texdatasize, 1,mpfFile); }
void MaterialPreviewDialog::buildPreviewBitmap( const Ogre::String &texName ) { const Ogre::uchar BytePerPixel = 8; // 读取原始image Ogre::Image *oriImage = getPreviewImage(texName); // 源大纹理的大小 size_t oriImageHeight = oriImage->getHeight(); size_t oriImageWidth = oriImage->getWidth(); Ogre::uchar *oriImageData = oriImage->getData(); // 分配一个足够大的空间来保存新建的image的数据 size_t newImagegetRowSpan = oriImageWidth*oriImage->getBPP()/BytePerPixel; // 新建的image的行宽(单位为字节) Ogre::uchar *newImageData = OGRE_ALLOC_T(Ogre::uchar, oriImageHeight*newImagegetRowSpan, Ogre::MEMCATEGORY_GENERAL);//new Ogre::uchar[oriImageHeight*newImagegetRowSpan]; Ogre::uchar *newImageDataPointer = newImageData; Ogre::uchar *oriImagedataPointer = oriImageData; // 把所选的纹理的数据提取出来,并创建一个新的image for ( Ogre::uint i=0; i<oriImageHeight; ++i ) { memcpy(newImageDataPointer, oriImagedataPointer, newImagegetRowSpan); newImageDataPointer += newImagegetRowSpan; oriImagedataPointer += oriImage->getRowSpan(); } Ogre::Image newImage; newImage.loadDynamicImage(newImageData,oriImageWidth,oriImageHeight,1,oriImage->getFormat(),true); // 如果所选纹理大于64*64,就先resize if ( oriImageWidth > mPreviewImageWidth || oriImageHeight > mPreviewImageHeight ) newImage.resize(mPreviewImageWidth, mPreviewImageHeight); // 如果有alpha,要与黑白图进行混合 if ( newImage.getHasAlpha() ) { Ogre::ColourValue col; for ( int i=0; i<mPreviewImageWidth; ++i ) { for ( int j=0; j<mPreviewImageWidth; ++j ) { col = newImage.getColourAt(j,i,0); float alphaValue = col.a; unsigned char r = col.r*255 * alphaValue; unsigned char g = col.g*255 * alphaValue; unsigned char b = col.b*255 * alphaValue; // 设置到image中 mCurrentPreviewImage.SetRGB(j,i,r,g,b); } } } // 没有alpha,就直接拷贝数据 else { Ogre::ColourValue col; for ( int i=0; i<mPreviewImageWidth; ++i ) { for ( int j=0; j<mPreviewImageWidth; ++j ) { col = newImage.getColourAt(j,i,0); unsigned char r = col.r*255; unsigned char g = col.g*255; unsigned char b = col.b*255; // 设置到image中 mCurrentPreviewImage.SetRGB(j,i,r,g,b); } } } }
void GlobalMap::read(ESM::GlobalMap& map) { const ESM::GlobalMap::Bounds& bounds = map.mBounds; if (bounds.mMaxX-bounds.mMinX < 0) return; if (bounds.mMaxY-bounds.mMinY < 0) return; if (bounds.mMinX > bounds.mMaxX || bounds.mMinY > bounds.mMaxY) throw std::runtime_error("invalid map bounds"); Ogre::Image image; Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream(&map.mImageData[0], map.mImageData.size())); image.load(stream, "png"); int xLength = (bounds.mMaxX-bounds.mMinX+1); int yLength = (bounds.mMaxY-bounds.mMinY+1); // Size of one cell in image space int cellImageSizeSrc = image.getWidth() / xLength; if (int(image.getHeight() / yLength) != cellImageSizeSrc) throw std::runtime_error("cell size must be quadratic"); // If cell bounds of the currently loaded content and the loaded savegame do not match, // we need to resize source/dest boxes to accommodate // This means nonexisting cells will be dropped silently int cellImageSizeDst = mCellSize; // Completely off-screen? -> no need to blit anything if (bounds.mMaxX < mMinX || bounds.mMaxY < mMinY || bounds.mMinX > mMaxX || bounds.mMinY > mMaxY) return; int leftDiff = (mMinX - bounds.mMinX); int topDiff = (bounds.mMaxY - mMaxY); int rightDiff = (bounds.mMaxX - mMaxX); int bottomDiff = (mMinY - bounds.mMinY); Ogre::Image::Box srcBox ( std::max(0, leftDiff * cellImageSizeSrc), std::max(0, topDiff * cellImageSizeSrc), std::min(image.getWidth(), image.getWidth() - rightDiff * cellImageSizeSrc), std::min(image.getHeight(), image.getHeight() - bottomDiff * cellImageSizeSrc)); Ogre::Image::Box destBox ( std::max(0, -leftDiff * cellImageSizeDst), std::max(0, -topDiff * cellImageSizeDst), std::min(mOverlayTexture->getWidth(), mOverlayTexture->getWidth() + rightDiff * cellImageSizeDst), std::min(mOverlayTexture->getHeight(), mOverlayTexture->getHeight() + bottomDiff * cellImageSizeDst)); // Looks like there is no interface for blitting from memory with src/dst boxes. // So we create a temporary texture for blitting. Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().createManual("@temp", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, image.getWidth(), image.getHeight(), 0, Ogre::PF_A8B8G8R8); tex->loadImage(image); mOverlayTexture->load(); mOverlayTexture->getBuffer()->blit(tex->getBuffer(), srcBox, destBox); if (srcBox.left == destBox.left && srcBox.right == destBox.right && srcBox.top == destBox.top && srcBox.bottom == destBox.bottom && int(image.getWidth()) == mWidth && int(image.getHeight()) == mHeight) mOverlayImage = image; else mOverlayTexture->convertToImage(mOverlayImage); Ogre::TextureManager::getSingleton().remove("@temp"); }
const Fairy::Action * BrushSelector::OnStartAutoTexAction( const wxTreeItemId &itemId, const wxString &brushName ) { // 启动自动纹理拼接action Fairy::Action* action = GetSceneManipulator()->_getAction("AutoTexPaintAction"); // 获取组的名称 wxString groupName = mBrushesTree->GetItemText(itemId); // 设置当前组的名称 action->setParameter( "%GroupName", AS_STRING(brushName) ); // 把之前的路径加上去 wxTreeItemId parentId = mBrushesTree->GetItemParent(itemId); wxTreeItemId rootId = mBrushesTree->GetRootItem(); while ( parentId != rootId ) { wxString parentText = mBrushesTree->GetItemText(parentId); parentText += '/'; groupName.Prepend( parentText ); parentId = mBrushesTree->GetItemParent(parentId); } groupName += "/"; // 获取该目录下的第一个节点 wxTreeItemIdValue dummy; wxTreeItemId childId = mBrushesTree->GetFirstChild(itemId,dummy); while ( childId.IsOk() == true ) { // 遍历每个节点,设置纹理名称 wxString texName = mBrushesTree->GetItemText(childId); childId = mBrushesTree->GetNextChild(itemId,dummy); if ( texName.find('|') == wxString::npos ) continue; action->setParameter( "%TextureName", AS_STRING(texName) ); } // 输入InputFinish表示纹理名称输入完毕 action->setParameter( "%TextureName", "InputFinish" ); // 判断纹理是否正确地进行了初始化 if ( action->getParameter("%IsInit") == "Yes" ) { GetSceneManipulator()->setActiveAction(action); return action; } else { // 启用simplepaintAction action = GetSceneManipulator()->_getAction("SimplePaintAction"); action->setParameter( "%TextureName", "InputBegin" ); // 获取该目录下的第一个节点 wxTreeItemIdValue dummy; wxTreeItemId childId = mBrushesTree->GetFirstChild(itemId,dummy); while ( childId.IsOk() == true ) { // 遍历每个节点,设置纹理名称 wxString texName = mBrushesTree->GetItemText(childId); childId = mBrushesTree->GetNextChild(itemId,dummy); if ( texName.find('|') == wxString::npos ) continue; const Fairy::TextureInfos ¤tPaintInfos = GetSceneManipulator()->getTextureInfos(mCurrentFileName.c_str()); const Fairy::TextureInfo ¤tPaintInfo = GetSceneManipulator()->getTextureInfo(mCurrentFileName.c_str(), texName.c_str()); Ogre::Image *previewImage = GetSceneManipulator()->getPreviewImage(currentPaintInfo.ownerTextureName); // 组成纹理信息字符串 Ogre::String texInfoString; texInfoString += currentPaintInfo.ownerTextureName; texInfoString += "|"; texInfoString += Ogre::StringConverter::toString(currentPaintInfo.height); texInfoString += "|"; texInfoString += Ogre::StringConverter::toString(currentPaintInfo.width); texInfoString += "|"; texInfoString += Ogre::StringConverter::toString(currentPaintInfo.leftCorner); texInfoString += "|"; texInfoString += Ogre::StringConverter::toString(currentPaintInfo.topCorner); texInfoString += "|"; texInfoString += Ogre::StringConverter::toString(previewImage->getHeight()); texInfoString += "|"; texInfoString += Ogre::StringConverter::toString(previewImage->getWidth()); texInfoString += "|"; texInfoString += Ogre::StringConverter::toString(currentPaintInfo.rotateType); action->setParameter( "%TextureName", AS_STRING(texInfoString) ); // 这里有个错误??,因为没有设置该纹理是否为普通纹理大小,所以如果这一个组中有一个大纹理,那么 // 它可能会只缩放到一格 } if ( action->getParameter("%IsInit") == "Yes" ) { GetSceneManipulator()->setActiveAction(action); return action; } else { // 为能成功初始化,先把active action设为NULL GetSceneManipulator()->setActiveAction(NULL); return NULL; } } }