示例#1
0
文件: scene.cpp 项目: Lazaroth/openmw
    void Scene::loadCell (CellStore *cell, Loading::Listener* loadingListener)
    {
        std::pair<CellStoreCollection::iterator, bool> result = mActiveCells.insert(cell);

        if(result.second)
        {
            float verts = ESM::Land::LAND_SIZE;
            float worldsize = ESM::Land::REAL_SIZE;

            // Load terrain physics first...
            if (cell->getCell()->isExterior())
            {
                ESM::Land* land =
                    MWBase::Environment::get().getWorld()->getStore().get<ESM::Land>().search(
                        cell->getCell()->getGridX(),
                        cell->getCell()->getGridY()
                    );
                if (land) {
                    // Actually only VHGT is needed here, but we'll need the rest for rendering anyway.
                    // Load everything now to reduce IO overhead.
                    const int flags = ESM::Land::DATA_VCLR|ESM::Land::DATA_VHGT|ESM::Land::DATA_VNML|ESM::Land::DATA_VTEX;
                    if (!land->isDataLoaded(flags))
                        land->loadData(flags);
                    mPhysics->addHeightField (
                        land->mLandData->mHeights,
                        cell->getCell()->getGridX(),
                        cell->getCell()->getGridY(),
                        0,
                        worldsize / (verts-1),
                        verts)
                    ;
                }
            }

            cell->respawn();

            // ... then references. This is important for adjustPosition to work correctly.
            /// \todo rescale depending on the state of a new GMST
            insertCell (*cell, true, loadingListener);

            mRendering.cellAdded (cell);
            bool waterEnabled = cell->getCell()->hasWater();
            mRendering.setWaterEnabled(waterEnabled);
            if (waterEnabled)
            {
                mPhysics->enableWater(cell->getWaterLevel());
                mRendering.setWaterHeight(cell->getWaterLevel());
            }
            else
                mPhysics->disableWater();

            mRendering.configureAmbient(*cell);
        }

        // register local scripts
        // ??? Should this go into the above if block ???
        MWBase::Environment::get().getWorld()->getLocalScripts().addCell (cell);
    }
示例#2
0
    int TerrainManager::getLtexIndexAt(int cellX, int cellY,
                                       int x, int y)
    {
        //check texture index falls within the 9 cell bounds
        //as this function can't cope with anything above that
        assert(x >= -ESM::Land::LAND_TEXTURE_SIZE &&
               y >= -ESM::Land::LAND_TEXTURE_SIZE &&
               "Trying to get land textures that are out of bounds");

        assert(x < 2*ESM::Land::LAND_TEXTURE_SIZE &&
               y < 2*ESM::Land::LAND_TEXTURE_SIZE &&
               "Trying to get land textures that are out of bounds");

        if ( x < 0 )
        {
            cellX--;
            x += ESM::Land::LAND_TEXTURE_SIZE;
        }
        else if ( x >= ESM::Land::LAND_TEXTURE_SIZE )
        {
            cellX++;
            x -= ESM::Land::LAND_TEXTURE_SIZE;
        }

        if ( y < 0 )
        {
            cellY--;
            y += ESM::Land::LAND_TEXTURE_SIZE;
        }
        else if ( y >= ESM::Land::LAND_TEXTURE_SIZE )
        {
            cellY++;
            y -= ESM::Land::LAND_TEXTURE_SIZE;
        }


        ESM::Land* land =
            MWBase::Environment::get().getWorld()->getStore().get<ESM::Land>().search(cellX, cellY);
        if ( land != NULL )
        {
            if (!land->isDataLoaded(ESM::Land::DATA_VTEX))
            {
                land->loadData(ESM::Land::DATA_VTEX);
            }

            return land->mLandData
                       ->mTextures[y * ESM::Land::LAND_TEXTURE_SIZE + x];
        }
        else
        {
            return 0;
        }
    }
示例#3
0
    const ESM::Land* TerrainStorage::getLand(int cellX, int cellY)
    {
        const MWWorld::ESMStore &esmStore =
            MWBase::Environment::get().getWorld()->getStore();
        ESM::Land* land = esmStore.get<ESM::Land>().search(cellX, cellY);
        if (!land)
            return NULL;

        const int flags = ESM::Land::DATA_VCLR|ESM::Land::DATA_VHGT|ESM::Land::DATA_VNML|ESM::Land::DATA_VTEX;
        if (!land->isDataLoaded(flags))
            land->loadData(flags);

        // TODO: unload land data when it's no longer needed

        return land;
    }
示例#4
0
    void GlobalMap::render (Loading::Listener* loadingListener)
    {
        Ogre::TexturePtr tex;

        const MWWorld::ESMStore &esmStore =
            MWBase::Environment::get().getWorld()->getStore();

        // get the size of the world
        MWWorld::Store<ESM::Cell>::iterator it = esmStore.get<ESM::Cell>().extBegin();
        for (; it != esmStore.get<ESM::Cell>().extEnd(); ++it)
        {
            if (it->getGridX() < mMinX)
                mMinX = it->getGridX();
            if (it->getGridX() > mMaxX)
                mMaxX = it->getGridX();
            if (it->getGridY() < mMinY)
                mMinY = it->getGridY();
            if (it->getGridY() > mMaxY)
                mMaxY = it->getGridY();
        }

        mWidth = mCellSize*(mMaxX-mMinX+1);
        mHeight = mCellSize*(mMaxY-mMinY+1);

        loadingListener->loadingOn();
        loadingListener->setLabel("Creating map");
        loadingListener->setProgressRange((mMaxX-mMinX+1) * (mMaxY-mMinY+1));
        loadingListener->setProgress(0);

        std::vector<Ogre::uchar> data (mWidth * mHeight * 3);

        for (int x = mMinX; x <= mMaxX; ++x)
        {
            for (int y = mMinY; y <= mMaxY; ++y)
            {
                ESM::Land* land = esmStore.get<ESM::Land>().search (x,y);

                if (land)
                {
                    int mask = ESM::Land::DATA_WNAM;
                    if (!land->isDataLoaded(mask))
                        land->loadData(mask);
                }

                for (int cellY=0; cellY<mCellSize; ++cellY)
                {
                    for (int cellX=0; cellX<mCellSize; ++cellX)
                    {
                        int vertexX = static_cast<int>(float(cellX)/float(mCellSize) * 9);
                        int vertexY = static_cast<int>(float(cellY) / float(mCellSize) * 9);


                        int texelX = (x-mMinX) * mCellSize + cellX;
                        int texelY = (mHeight-1) - ((y-mMinY) * mCellSize + cellY);

                        unsigned char r,g,b;

                        float y = 0;
                        if (land && land->mDataTypes & ESM::Land::DATA_WNAM)
                            y = (land->mLandData->mWnam[vertexY * 9 + vertexX] << 4) / 2048.f;
                        else
                            y = (SCHAR_MIN << 4) / 2048.f;
                        if (y < 0)
                        {
                            r = static_cast<unsigned char>(14 * y + 38);
                            g = static_cast<unsigned char>(20 * y + 56);
                            b = static_cast<unsigned char>(18 * y + 51);
                        }
                        else if (y < 0.3f)
                        {
                            if (y < 0.1f)
                                y *= 8.f;
                            else
                            {
                                y -= 0.1f;
                                y += 0.8f;
                            }
                            r = static_cast<unsigned char>(66 - 32 * y);
                            g = static_cast<unsigned char>(48 - 23 * y);
                            b = static_cast<unsigned char>(33 - 16 * y);
                        }
                        else
                        {
                            y -= 0.3f;
                            y *= 1.428f;
                            r = static_cast<unsigned char>(34 - 29 * y);
                            g = static_cast<unsigned char>(25 - 20 * y);
                            b = static_cast<unsigned char>(17 - 12 * y);
                        }

                        data[texelY * mWidth * 3 + texelX * 3] = r;
                        data[texelY * mWidth * 3 + texelX * 3+1] = g;
                        data[texelY * mWidth * 3 + texelX * 3+2] = b;
                    }
                }
                loadingListener->increaseProgress();
                if (land)
                    land->unloadData();
            }
        }

        Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream(&data[0], data.size()));

        tex = Ogre::TextureManager::getSingleton ().createManual ("GlobalMap.png", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
            Ogre::TEX_TYPE_2D, mWidth, mHeight, 0, Ogre::PF_B8G8R8, Ogre::TU_STATIC);
        tex->loadRawData(stream, mWidth, mHeight, Ogre::PF_B8G8R8);

        tex->load();

        mOverlayTexture = Ogre::TextureManager::getSingleton().createManual("GlobalMapOverlay", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
            Ogre::TEX_TYPE_2D, mWidth, mHeight, 0, Ogre::PF_A8B8G8R8, Ogre::TU_DYNAMIC, this);

        clear();

        loadingListener->loadingOff();
    }
示例#5
0
    void GlobalMap::render (Loading::Listener* loadingListener)
    {
        const MWWorld::ESMStore &esmStore =
            MWBase::Environment::get().getWorld()->getStore();

        // get the size of the world
        MWWorld::Store<ESM::Cell>::iterator it = esmStore.get<ESM::Cell>().extBegin();
        for (; it != esmStore.get<ESM::Cell>().extEnd(); ++it)
        {
            if (it->getGridX() < mMinX)
                mMinX = it->getGridX();
            if (it->getGridX() > mMaxX)
                mMaxX = it->getGridX();
            if (it->getGridY() < mMinY)
                mMinY = it->getGridY();
            if (it->getGridY() > mMaxY)
                mMaxY = it->getGridY();
        }

        mWidth = mCellSize*(mMaxX-mMinX+1);
        mHeight = mCellSize*(mMaxY-mMinY+1);

        loadingListener->loadingOn();
        loadingListener->setLabel("Creating map");
        loadingListener->setProgressRange((mMaxX-mMinX+1) * (mMaxY-mMinY+1));
        loadingListener->setProgress(0);

        osg::ref_ptr<osg::Image> image = new osg::Image;
        image->allocateImage(mWidth, mHeight, 1, GL_RGB, GL_UNSIGNED_BYTE);
        unsigned char* data = image->data();

        for (int x = mMinX; x <= mMaxX; ++x)
        {
            for (int y = mMinY; y <= mMaxY; ++y)
            {
                ESM::Land* land = esmStore.get<ESM::Land>().search (x,y);

                if (land)
                {
                    int mask = ESM::Land::DATA_WNAM;
                    if (!land->isDataLoaded(mask))
                        land->loadData(mask);
                }

                const ESM::Land::LandData *landData =
                    land ? land->getLandData (ESM::Land::DATA_WNAM) : 0;

                for (int cellY=0; cellY<mCellSize; ++cellY)
                {
                    for (int cellX=0; cellX<mCellSize; ++cellX)
                    {
                        int vertexX = static_cast<int>(float(cellX)/float(mCellSize) * 9);
                        int vertexY = static_cast<int>(float(cellY) / float(mCellSize) * 9);

                        int texelX = (x-mMinX) * mCellSize + cellX;
                        int texelY = (y-mMinY) * mCellSize + cellY;

                        unsigned char r,g,b;

                        float y = 0;
                        if (landData)
                            y = (landData->mWnam[vertexY * 9 + vertexX] << 4) / 2048.f;
                        else
                            y = (SCHAR_MIN << 4) / 2048.f;
                        if (y < 0)
                        {
                            r = static_cast<unsigned char>(14 * y + 38);
                            g = static_cast<unsigned char>(20 * y + 56);
                            b = static_cast<unsigned char>(18 * y + 51);
                        }
                        else if (y < 0.3f)
                        {
                            if (y < 0.1f)
                                y *= 8.f;
                            else
                            {
                                y -= 0.1f;
                                y += 0.8f;
                            }
                            r = static_cast<unsigned char>(66 - 32 * y);
                            g = static_cast<unsigned char>(48 - 23 * y);
                            b = static_cast<unsigned char>(33 - 16 * y);
                        }
                        else
                        {
                            y -= 0.3f;
                            y *= 1.428f;
                            r = static_cast<unsigned char>(34 - 29 * y);
                            g = static_cast<unsigned char>(25 - 20 * y);
                            b = static_cast<unsigned char>(17 - 12 * y);
                        }

                        data[texelY * mWidth * 3 + texelX * 3] = r;
                        data[texelY * mWidth * 3 + texelX * 3+1] = g;
                        data[texelY * mWidth * 3 + texelX * 3+2] = b;
                    }
                }
                loadingListener->increaseProgress();
                if (land)
                    land->unloadData();
            }
        }

        mBaseTexture = new osg::Texture2D;
        mBaseTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
        mBaseTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
        mBaseTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
        mBaseTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
        mBaseTexture->setImage(image);
        mBaseTexture->setResizeNonPowerOfTwoHint(false);

        clear();

        loadingListener->loadingOff();
    }
示例#6
0
    void TerrainManager::cellAdded(MWWorld::Ptr::CellStore *store)
    {
        const int cellX = store->mCell->getGridX();
        const int cellY = store->mCell->getGridY();

        ESM::Land* land =
            MWBase::Environment::get().getWorld()->getStore().get<ESM::Land>().search(cellX, cellY);
        if (land == NULL) // no land data means we're not going to create any terrain.
            return;

        int dataRequired = ESM::Land::DATA_VHGT | ESM::Land::DATA_VCLR;
        if (!land->isDataLoaded(dataRequired))
        {
            land->loadData(dataRequired);
        }

        //split the cell terrain into four segments
        const int numTextures = ESM::Land::LAND_TEXTURE_SIZE/2;

        for ( int x = 0; x < 2; x++ )
        {
            for ( int y = 0; y < 2; y++ )
            {
                Terrain::ImportData terrainData =
                    mTerrainGroup.getDefaultImportSettings();

                const int terrainX = cellX * 2 + x;
                const int terrainY = cellY * 2 + y;

                //it makes far more sense to reallocate the memory here,
                //and let Ogre deal with it due to the issues with deleting
                //it at the wrong time if using threads (Which Terrain does)
                terrainData.inputFloat = OGRE_ALLOC_T(float,
                                                      mLandSize*mLandSize,
                                                      MEMCATEGORY_GEOMETRY);

                //copy the height data row by row
                for ( int terrainCopyY = 0; terrainCopyY < mLandSize; terrainCopyY++ )
                {
                                           //the offset of the current segment
                    const size_t yOffset = y * (mLandSize-1) * ESM::Land::LAND_SIZE +
                                           //offset of the row
                                           terrainCopyY * ESM::Land::LAND_SIZE;
                    const size_t xOffset = x * (mLandSize-1);

                    memcpy(&terrainData.inputFloat[terrainCopyY*mLandSize],
                           &land->mLandData->mHeights[yOffset + xOffset],
                           mLandSize*sizeof(float));
                }

                std::map<uint16_t, int> indexes;
                initTerrainTextures(&terrainData, cellX, cellY,
                                    x * numTextures, y * numTextures,
                                    numTextures, indexes, land->mPlugin);

                if (mTerrainGroup.getTerrain(terrainX, terrainY) == NULL)
                {
                    mTerrainGroup.defineTerrain(terrainX, terrainY, &terrainData);

                    mTerrainGroup.loadTerrain(terrainX, terrainY, true);

                    Terrain* terrain = mTerrainGroup.getTerrain(terrainX, terrainY);
                    initTerrainBlendMaps(terrain,
                                         cellX, cellY,
                                         x * numTextures, y * numTextures,
                                         numTextures,
                                         indexes);
                    terrain->setVisibilityFlags(RV_Terrain);
                    terrain->setRenderQueueGroup(RQG_Main);

                    // disable or enable global colour map (depends on available vertex colours)
                    if ( land->mLandData->mUsingColours )
                    {
                        TexturePtr vertex = getVertexColours(land,
                                                             cellX, cellY,
                                                             x*(mLandSize-1),
                                                             y*(mLandSize-1),
                                                             mLandSize);

                        mActiveProfile->setGlobalColourMapEnabled(true);
                        mActiveProfile->setGlobalColourMap (terrain, vertex->getName());
                    }
                    else
                        mActiveProfile->setGlobalColourMapEnabled (false);
                }
            }
        }

        // when loading from a heightmap, Ogre::Terrain does not update the derived data (normal map, LOD)
        // synchronously, even if we supply synchronous = true parameter to loadTerrain.
        // the following to be the only way to make sure derived data is ready when rendering the next frame.
        while (mTerrainGroup.isDerivedDataUpdateInProgress())
        {
           // we need to wait for this to finish
           OGRE_THREAD_SLEEP(5);
           Root::getSingleton().getWorkQueue()->processResponses();
        }

        mTerrainGroup.freeTemporaryResources();
    }