Beispiel #1
0
 void ReliefApp::GenerateRelief()
 {
     //Get depth data
     Ogre::TexturePtr depthTex = Ogre::TextureManager::getSingleton().createManual(  
         "DepthTexture",      // name   
         Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,  
         Ogre::TEX_TYPE_2D,   // type   
         512,  // width   
         512,  // height   
         0,                   // number of mipmaps   
         //Ogre::PF_B8G8R8A8,   // pixel format
         Ogre::PF_FLOAT32_R,
         Ogre::TU_RENDERTARGET
         ); 
     Ogre::RenderTarget* pTarget = depthTex->getBuffer()->getRenderTarget();
     Ogre::Camera* pOrthCam = MagicCore::RenderSystem::GetSingleton()->GetMainCamera();
     pOrthCam->setProjectionType(Ogre::PT_ORTHOGRAPHIC);
     pOrthCam->setOrthoWindow(3, 3);
     pOrthCam->setPosition(0, 0, 3);
     pOrthCam->lookAt(0, 0, 0);
     pOrthCam->setAspectRatio(1.0);
     pOrthCam->setNearClipDistance(0.5);
     pOrthCam->setFarClipDistance(5);
     Ogre::Viewport* pViewport = pTarget->addViewport(pOrthCam);
     pViewport->setDimensions(0, 0, 1, 1);
     MagicCore::RenderSystem::GetSingleton()->RenderLightMesh3D("RenderMesh", "Depth", mpLightMesh);
     MagicCore::RenderSystem::GetSingleton()->Update();
     Ogre::Image img;
     depthTex->convertToImage(img);
     std::vector<double> heightField(512 * 512);
     for(int x = 0; x < 512; x++)  
     {  
         for(int y = 0; y < 512; y++)  
         {
             heightField.at(x * 512 + y) = (img.getColourAt(x, 511 - y, 0))[1];
         }
     }
     Ogre::TextureManager::getSingleton().remove("DepthTexture");
     //
     MagicDGP::LightMesh3D* pReliefMesh = MagicDGP::ReliefGeneration::PlaneReliefFromHeightField(heightField, 511, 511);
     //MagicDGP::LightMesh3D* pReliefMesh = MagicDGP::ReliefGeneration::CylinderReliefFromHeightField(heightField, 511, 511);
     if (pReliefMesh != NULL)
     {
         delete mpLightMesh;
         mpLightMesh = pReliefMesh;
         mpLightMesh->UnifyPosition(2);
         mpLightMesh->UpdateNormal();
     }
     MagicCore::RenderSystem::GetSingleton()->SetupCameraDefaultParameter();
     MagicCore::RenderSystem::GetSingleton()->RenderLightMesh3D("RenderMesh", "MyCookTorrance", mpLightMesh);
 }
Beispiel #2
0
//-----------------------------------------------------------------------------------------
void CTerrainGroupEditor::setBrushName(const std::string& brush)
{
    mBrushName = brush;
    if(!mDecalTexture.isNull())
    {
        Ogre::Image img;
        img.load(brush,"Brushes");
        
        unsigned char *dataptr = OGRE_ALLOC_T(unsigned char, img.getWidth() * img.getHeight() * 3, Ogre::MEMCATEGORY_GEOMETRY);
        Ogre::PixelBox resultbox(img.getWidth(),img.getHeight(),1,Ogre::PF_B8G8R8,dataptr);
        Ogre::PixelUtil::bulkPixelConversion(img.getPixelBox(), resultbox);

        resultbox.setConsecutive();
        int pos = 0;
        Ogre::ColourValue colval;
        for(unsigned int x = 0;x < img.getHeight() * img.getWidth();x++)
        {
                dataptr[pos] = 0;
                dataptr[pos + 1] = 0;
                dataptr[pos + 2] *= 0.8f;
                pos += 3;
        }

        mDecalTexture->setHeight(img.getHeight());
        mDecalTexture->setWidth(img.getWidth());
        Ogre::HardwarePixelBufferSharedPtr ptr = mDecalTexture->getBuffer();
        ptr->blitFromMemory(resultbox);
        OGRE_FREE(dataptr, Ogre::MEMCATEGORY_GEOMETRY);

        img.resize(mBrushSize, mBrushSize);
        img.resize(BRUSH_DATA_SIZE, BRUSH_DATA_SIZE);
        pos = 0;
        Ogre::ColourValue cval;
        for(unsigned int y = 0;y < BRUSH_DATA_SIZE ;y++)
        {
            pos = ((BRUSH_DATA_SIZE - 1) - y) * BRUSH_DATA_SIZE;
            for(unsigned int x = 0;x < BRUSH_DATA_SIZE ;x++)
            {
                cval = img.getColourAt(x,y,0);
                mBrushData[pos] = cval.r;
                pos++;
            }
        }
    }
Beispiel #3
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 TerrainGeometryManager::initBlendMaps(int x, int z, Ogre::Terrain* terrain )
{
	bool debugBlendMaps = BOPT("DebugBlendMaps", false);

	int layerCount = terrain->getLayerCount();
	for (int i = 1; i < layerCount; i++)
	{
		blendLayerInfo_t &bi = blendInfo[i];

		if(bi.blendMapTextureFilename.empty()) continue;

		Ogre::Image img;
		//std::pair<uint8,uint8> textureIndex = terrain->getLayerBlendTextureIndex(i);
		//uint8 bti = terrain->getBlendTextureIndex(i);
		try
		{
			img.load(bi.blendMapTextureFilename, ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME);
		} catch(Exception &e)
		{
			LOG("Error loading blendmap: " + bi.blendMapTextureFilename + " : " + e.getFullDescription());
			continue;
		}

		TerrainLayerBlendMap *blendmap = terrain->getLayerBlendMap(i);

		// resize that blending map so it will fit
		Ogre::uint32 blendmapSize = terrain->getLayerBlendMapSize();
		if (img.getWidth() != blendmapSize)
			img.resize(blendmapSize, blendmapSize);

		// now to the ugly part
		float* ptr = blendmap->getBlendPointer();
		for (Ogre::uint32 z = 0; z != blendmapSize; z++)
		{
			for (Ogre::uint32 x = 0; x != blendmapSize; x++)
			{
				Ogre::ColourValue c = img.getColourAt(x, z, 0);
				float alpha = bi.alpha;
				if      (bi.blendMode == 'R')
					*ptr++ = c.r * alpha;
				else if (bi.blendMode == 'G')
					*ptr++ = c.g * alpha;
				else if (bi.blendMode == 'B')
					*ptr++ = c.b * alpha;
				else if (bi.blendMode == 'A')
					*ptr++ = c.a * alpha;
			}
		}
		blendmap->dirty();
		blendmap->update();
	}

	if (debugBlendMaps)
	{
		for (int i = 1; i < layerCount; i++)
		{
			Ogre::TerrainLayerBlendMap* blendMap = terrain->getLayerBlendMap(i);
			Ogre::uint32 blendmapSize = terrain->getLayerBlendMapSize();
			Ogre::Image img;
			unsigned short *idata = OGRE_ALLOC_T(unsigned short, blendmapSize * blendmapSize, Ogre::MEMCATEGORY_RESOURCE);
			float scale = 65535.0f;
			for (unsigned int x = 0; x < blendmapSize; x++)
				for (unsigned int z = 0; z < blendmapSize; z++)
					idata[x + z * blendmapSize] = (unsigned short)(blendMap->getBlendValue(x, blendmapSize - z) * scale);
			img.loadDynamicImage((Ogre::uchar*)(idata), blendmapSize, blendmapSize, Ogre::PF_L16);
			std::string fileName = "blendmap_layer_" + Ogre::StringConverter::toString(i) + ".png";
			img.save(fileName);
			OGRE_FREE(idata, Ogre::MEMCATEGORY_RESOURCE);
		}
	}
}
Beispiel #5
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);    
    }
}
Beispiel #6
0
// -------------------------------------------------------------------------
void Terrain_Demo::init(Ogre::Root *root, Ogre::RenderWindow *win, OgreBulletApplication *application)
{
    mCameraMove = 1;

    mHelpKeys.clear();
    mHelpKeys.push_back(BASIC_HELP_INFO0);
    mHelpKeys.push_back(BASIC_HELP_INFO1);
    mHelpKeys.push_back(BASIC_HELP_INFO2);
    mHelpKeys.push_back(BASIC_HELP_INFO3);
    mHelpKeys.push_back(BASIC_HELP_INFO4);
    mHelpKeys.push_back(BASIC_HELP_INFO5);
    mHelpKeys.push_back(BASIC_HELP_INFO6);
    mHelpKeys.push_back("Use Arrow Key to move Car.");

// reset
    for (int i = 0; i < 4; i++)
    {
        mWheelsEngine[i] = 0;
        mWheelsSteerable[i] = 0;
    }
    mWheelsEngineCount = 2;
    mWheelsEngine[0] = 0;
    mWheelsEngine[1] = 1;
    mWheelsEngine[2] = 2;
    mWheelsEngine[3] = 3;

    mWheelsSteerableCount = 2;
    mWheelsSteerable[0] = 0;
    mWheelsSteerable[1] = 1;
    //mWheelsSteerable[2] = 2;
    //mWheelsSteerable[3] = 3;

    mWheelEngineStyle = 0;
    mWheelSteeringStyle = 0;

    mSteeringLeft = false;
    mSteeringRight = false;

    mEngineForce = 0;
    mSteering = 0;

    // ------------------------
    // Start OgreScene
    mSceneMgr = root->createSceneManager("TerrainSceneManager", "BulletTerrain");

    mCamera = mSceneMgr->createCamera("Cam");
    //mCamera->setFOVy(Degree(90));
    mCamera->setNearClipDistance(0.1);
    mCamera->setFarClipDistance(1000);
    Viewport *vp = win->addViewport(mCamera);
    vp->setBackgroundColour(ColourValue(0,0,0));
    // Alter the camera aspect ratio to match the viewport
    mCamera->setAspectRatio(
        Real(vp->getActualWidth()) / Real(vp->getActualHeight()));
    mCamera->setPosition(CameraStart + terrain_Shift);
    mCamera->lookAt(CarPosition + terrain_Shift);


    // Create a terrain
    std::string terrain_cfg("terrain.cfg");
    mSceneMgr->setWorldGeometry(terrain_cfg);

    OgreBulletListener::init(root, win, application);

    // ------------------------
    // add lights
    setBasicLight();

    // ------------------------
    // Add the Gui
    setPhysicGUI();
    // ------------------------
    // Start Bullet
    initWorld();

    // ------------------------
    // Add the ground

    // 0.1, 0.8
    //addStaticPlane(0.3, 0.8);

    {
        Ogre::ConfigFile config;

        config.loadFromResourceSystem(terrain_cfg, ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME, "=", true);

        unsigned page_size = Ogre::StringConverter::parseUnsignedInt(config.getSetting("PageSize"));

        Ogre::Vector3 terrainScale(Ogre::StringConverter::parseReal(config.getSetting("PageWorldX")) / (page_size - 1),
                                   Ogre::StringConverter::parseReal(config.getSetting("MaxHeight")),
                                   Ogre::StringConverter::parseReal(config.getSetting("PageWorldZ")) / (page_size - 1));

        Ogre::String terrainfileName = config.getSetting("Heightmap.image");

        float *heights = new float[page_size*page_size];

        Ogre::Image terrainHeightMap;
        terrainHeightMap.load(terrainfileName, Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME);

        for (unsigned y = 0; y < page_size; ++y)
        {
            for (unsigned x = 0; x < page_size; ++x)
            {
                Ogre::ColourValue color = terrainHeightMap.getColourAt(x, y, 0);
                heights[x + y * page_size] = color.r;
            }
        }

        mTerrainShape = new HeightmapCollisionShape(page_size,
                page_size,
                terrainScale,
                heights,
                true);

        RigidBody *defaultTerrainBody = new RigidBody("Terrain",
                mWorld);

        const float terrainBodyRestitution = 0.1f;
        const float terrainBodyFriction    = 0.8f;

        Ogre::Vector3 terrainShiftPos( (terrainScale.x * (page_size - 1) / 2), \
                                       0,
                                       (terrainScale.z * (page_size - 1) / 2));

        terrainShiftPos.y = terrainScale.y / 2 * terrainScale.y;

        Ogre::SceneNode* pTerrainNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
        defaultTerrainBody->setStaticShape (pTerrainNode, mTerrainShape, terrainBodyRestitution, terrainBodyFriction, terrainShiftPos);

        mBodies.push_back(defaultTerrainBody);
        mShapes.push_back(mTerrainShape);
    }




    // create obstacle in front of car
    addCube("obstacle", Ogre::Vector3(13,  -5.25, -5) + terrain_Shift ,  Quaternion(Radian(Degree(22.5)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0);
    addCube("obstacle", Ogre::Vector3(15,  -5.25, -5) + terrain_Shift ,  Quaternion(Radian(Degree(22.5)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0);
    addCube("obstacle", Ogre::Vector3(17,  -5.25, -5) + terrain_Shift ,  Quaternion(Radian(Degree(22.5)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0);

    addCube("obstacle", Ogre::Vector3(13,  -5.25, -10) + terrain_Shift , Quaternion(Radian(Degree(-22.5)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0);
    addCube("obstacle", Ogre::Vector3(15,  -5.25, -10) + terrain_Shift , Quaternion(Radian(Degree(-22.5)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0);
    addCube("obstacle", Ogre::Vector3(17,  -5.25, -10) + terrain_Shift , Quaternion(Radian(Degree(-22.5)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0);

    // create obstacle a bit aside
    addCube("obstacle", Ogre::Vector3(-2,  0, -5) + terrain_Shift ,  Quaternion(Radian(Degree(45.0)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0);
    addCube("obstacle", Ogre::Vector3(0,  0, -5) + terrain_Shift ,   Quaternion(Radian(Degree(45.0)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0);
    addCube("obstacle", Ogre::Vector3(2,  0, -5) + terrain_Shift ,   Quaternion(Radian(Degree(45.0)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0);

    addCube("obstacle", Ogre::Vector3(-2,  0, -10) + terrain_Shift , Quaternion(Radian(Degree(-45.0)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0);
    addCube("obstacle", Ogre::Vector3(0,  0, -10) + terrain_Shift ,  Quaternion(Radian(Degree(-45.0)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0);
    addCube("obstacle", Ogre::Vector3(2,  0, -10) + terrain_Shift ,  Quaternion(Radian(Degree(-45.0)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0);

    // create obstacle just for fun
    addCube("obstacle", Ogre::Vector3(25, -10, -25) + terrain_Shift , Quaternion(Radian(Degree(45.0)), Ogre::Vector3::UNIT_Z), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0);
    addCube("obstacle", Ogre::Vector3(25, -10, -27) + terrain_Shift , Quaternion(Radian(Degree(45.0)), Ogre::Vector3::UNIT_Z), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0);
    addCube("obstacle", Ogre::Vector3(25, -10, -29) + terrain_Shift , Quaternion(Radian(Degree(45.0)), Ogre::Vector3::UNIT_Z), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0);




    /// create vehicle
    {
        const Ogre::Vector3 chassisShift(0, 1.0, 0);
        float connectionHeight = 0.7f;

        mChassis = mSceneMgr->createEntity(
                       "chassis" + StringConverter::toString(mNumEntitiesInstanced++),
                       "chassis.mesh");

        SceneNode *node = mSceneMgr->getRootSceneNode ()->createChildSceneNode ();

        SceneNode *chassisnode = node->createChildSceneNode ();
        chassisnode->attachObject (mChassis);
        chassisnode->setPosition (chassisShift);


        mChassis->setQueryFlags (GEOMETRY_QUERY_MASK);
#if (OGRE_VERSION < ((1 << 16) | (5 << 8) | 0)) // only applicable before shoggoth (1.5.0)
        mChassis->setNormaliseNormals(true);
#endif
        mChassis->setCastShadows(true);



        CompoundCollisionShape* compound = new CompoundCollisionShape();

        BoxCollisionShape* chassisShape = new BoxCollisionShape(Ogre::Vector3(1.f,0.75f,2.1f));
        compound->addChildShape(chassisShape, chassisShift);

        mCarChassis = new WheeledRigidBody("carChassis", mWorld);

        mCarChassis->setShape(node,
                              compound,
                              0.6, //restitution
                              0.6, //friction
                              800, //bodyMass
                              CarPosition + terrain_Shift,
                              Quaternion::IDENTITY);

        mCarChassis->setDamping(0.2, 0.2);

        mCarChassis->disableDeactivation();
        mTuning = new VehicleTuning(gSuspensionStiffness,
                                    gSuspensionCompression,
                                    gSuspensionDamping,
                                    gMaxSuspensionTravelCm,
                                    gMaxSuspensionForce,
                                    gFrictionSlip);

        mVehicleRayCaster = new VehicleRayCaster(mWorld);
        mVehicle = new RaycastVehicle(mCarChassis, mTuning, mVehicleRayCaster);

        {
            int rightIndex = 0;
            int upIndex = 1;
            int forwardIndex = 2;

            mVehicle->setCoordinateSystem(rightIndex, upIndex, forwardIndex);

            Ogre::Vector3 wheelDirectionCS0(0,-1,0);
            Ogre::Vector3 wheelAxleCS(-1,0,0);

            for (size_t i = 0; i < 4; i++)
            {
                mWheels[i] = mSceneMgr->createEntity(
                                 "wheel" + StringConverter::toString(mNumEntitiesInstanced++),
                                 "wheel.mesh");

                mWheels[i]->setQueryFlags (GEOMETRY_QUERY_MASK);
#if (OGRE_VERSION < ((1 << 16) | (5 << 8) | 0)) // only applicable before shoggoth (1.5.0)
                mWheels[i]->setNormaliseNormals(true);
#endif
                mWheels[i]->setCastShadows(true);

                mWheelNodes[i] = mSceneMgr->getRootSceneNode ()->createChildSceneNode ();
                mWheelNodes[i]->attachObject (mWheels[i]);

            }

            {
                bool isFrontWheel = true;

                Ogre::Vector3 connectionPointCS0 (
                    CUBE_HALF_EXTENTS-(0.3*gWheelWidth),
                    connectionHeight,
                    2*CUBE_HALF_EXTENTS-gWheelRadius);


                mVehicle->addWheel(
                    mWheelNodes[0],
                    connectionPointCS0,
                    wheelDirectionCS0,
                    wheelAxleCS,
                    gSuspensionRestLength,
                    gWheelRadius,
                    isFrontWheel, gWheelFriction, gRollInfluence);

                connectionPointCS0 = Ogre::Vector3(
                                         -CUBE_HALF_EXTENTS+(0.3*gWheelWidth),
                                         connectionHeight,
                                         2*CUBE_HALF_EXTENTS-gWheelRadius);


                mVehicle->addWheel(
                    mWheelNodes[1],
                    connectionPointCS0,
                    wheelDirectionCS0,
                    wheelAxleCS,
                    gSuspensionRestLength,
                    gWheelRadius,
                    isFrontWheel, gWheelFriction, gRollInfluence);


                connectionPointCS0 = Ogre::Vector3(
                                         -CUBE_HALF_EXTENTS+(0.3*gWheelWidth),
                                         connectionHeight,
                                         -2*CUBE_HALF_EXTENTS+gWheelRadius);

                isFrontWheel = false;
                mVehicle->addWheel(
                    mWheelNodes[2],
                    connectionPointCS0,
                    wheelDirectionCS0,
                    wheelAxleCS,
                    gSuspensionRestLength,
                    gWheelRadius,
                    isFrontWheel, gWheelFriction, gRollInfluence);

                connectionPointCS0 = Ogre::Vector3(
                                         CUBE_HALF_EXTENTS-(0.3*gWheelWidth),
                                         connectionHeight,
                                         -2*CUBE_HALF_EXTENTS+gWheelRadius);

                mVehicle->addWheel(
                    mWheelNodes[3],
                    connectionPointCS0,
                    wheelDirectionCS0,
                    wheelAxleCS,
                    gSuspensionRestLength,
                    gWheelRadius,
                    isFrontWheel, gWheelFriction, gRollInfluence);

                //mVehicle->setWheelsAttached();

            }

        }
    }

}
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);
			}
		}
	}
}