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() ); } }
/* ----------------------------------------------------------------------- | 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; }