⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 etsplattingmanager.cpp

📁 etm2.2是基于Ogre引擎开发的地形库
💻 CPP
📖 第 1 页 / 共 2 页
字号:
          }
        }
      }

      void updateTextures()
      {
        // update all map textures
        for (uint i = 0; i < numMaps; ++i)
          maps[i]->updateTexture();
      }


      // helper function for createBaseTexture
      float interpolateWeight(size_t x, size_t y, size_t maxX, size_t maxY, size_t channel)
      {
        // get base position and interpolation
        float realPosX = float(x) * width / maxX;
        float realPosY = float(y) * height / maxY;
        uint posX = (uint)realPosX, posY = (uint)realPosY;
        float interpX = realPosX - posX, interpY = realPosY - posY;
        // adjust if at borders
        if (posX == width-1)
        {
          --posX;
          interpX = 1.0f;
        }
        if (posY == height-1)
        {
          --posY;
          interpY = 1.0f;
        }
        float interpXi = 1.0f-interpX, interpYi = 1.0f-interpY;
        size_t m = channel/channels;
        uint c = (uint) (channel%channels);

        float val = maps[m]->getValue(posX, posY, c) * interpXi * interpYi;
        val += maps[m]->getValue(posX+1, posY, c) * interpX * interpYi;
        val += maps[m]->getValue(posX+1, posY+1, c) * interpX * interpY;
        val += maps[m]->getValue(posX, posY+1, c) * interpXi * interpY;
        val /= 255;
        return val;
      }

    };

  }




  SplattingManager::SplattingManager(const string& baseName, const string& group, uint width, uint height, uint channels)
  {
    if (channels < 1 || channels > 4)
      OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Number of channels per texture must be between 1 and 4", "SplattingManager::SplattingManager");

    mImpl = new Impl::SplattingImpl();
    mImpl->baseName = baseName;
    mImpl->group = group;
    mImpl->width = width;
    mImpl->height = height;
    mImpl->channels = channels;
    mImpl->numTextures = 0;
    mImpl->numMaps = 0;
  }

  SplattingManager::~SplattingManager()
  {
    for (uint i = 0; i < mImpl->numMaps; ++i)
      delete mImpl->maps[i];
    delete mImpl;
  }

  void SplattingManager::setNumTextures(uint numTextures)
  {
    // the number of maps needed depends on the number of channels per texture
    if (numTextures == 0)
      setNumMaps(0);
    else
      setNumMaps((numTextures-1) / mImpl->channels + 1);
  }

  uint SplattingManager::getNumTextures() const
  {
    return mImpl->numTextures;
  }

  void SplattingManager::setNumMaps(uint numMaps)
  {
    mImpl->numMaps = numMaps;
    mImpl->numTextures = mImpl->numMaps * mImpl->channels;

    // add maps if we don't have enough
    for (size_t i = mImpl->maps.size(); i <= mImpl->numMaps; ++i)
    {
      mImpl->maps.push_back(new Impl::CoverageMap(mImpl->baseName+StringConverter::toString(i),
        mImpl->group, mImpl->width, mImpl->height, mImpl->channels, i != 0));
    }

    // remove maps if there are too many
    for (size_t i = mImpl->maps.size(); i > mImpl->numMaps; --i)
    {
      delete *mImpl->maps.rbegin();
      mImpl->maps.pop_back();
    }
  }

  uint SplattingManager::getNumMaps() const
  {
    return mImpl->numMaps;
  }

  NameList SplattingManager::getMapTextureNames() const
  {
    NameList names;
    for (size_t i = 0; i < mImpl->maps.size(); ++i)
      names.push_back(mImpl->maps[i]->getName());
    return names;
  }

  void SplattingManager::loadMapFromImage(uint mapNum, const Image& image)
  {
    mImpl->maps[mapNum]->loadFromImage(image);
  }

  void SplattingManager::saveMapToImage(uint mapNum, Image& image)
  {
    mImpl->maps[mapNum]->saveToImage(image);
  }


  void SplattingManager::paint(uint textureNum, int x, int y, const Brush& brush, float intensity)
  {
    // positions given are supposed to be the mid of the brush
    // so adjust accordingly
    x -= (int)brush.getWidth()/2;
    y -= (int)brush.getHeight()/2;

    // iterate over all fields of the brush array and apply them to the map textures
    // if they lie within the bounds
    for (size_t i = 0; i < brush.getWidth(); ++i)
    {
      int posX = x + (int)i;
      if (posX < 0 || posX >= (int)mImpl->width)
        continue;
      for (size_t j = 0; j < brush.getHeight(); ++j)
      {
        int posY = y + (int)j;
        if (posY < 0 || posY >= (int)mImpl->height)
          continue;

        mImpl->paint(textureNum, (uint)posX, (uint)posY, brush.at(i, j) * intensity);
      }
    }

    // finally, update the textures
    mImpl->updateTextures();
  }


  void SplattingManager::createColourMap(Image& image, const ColourList& colours)
  {
    if (colours.size() > mImpl->numTextures)
      OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Given more colours than texture channels available.", __FUNCTION__);

    uchar* data = new uchar[mImpl->width*mImpl->height*3];

    for (size_t y = 0; y < mImpl->height; ++y)
    {
      for (size_t x = 0; x < mImpl->width; ++x)
      {
        ColourValue val (0, 0, 0);
        for (size_t i = 0; i < colours.size(); ++i)
        {
          size_t m = i / mImpl->channels;
          uint t = (uint) (i % mImpl->channels);
          val += colours[i] * (float(mImpl->maps[m]->getValue((uint)x, (uint)y, t)) / 255);
        }

        size_t pos = (x + y * mImpl->width) * 3;
        data[pos+0] = uchar(255*val.r);
        data[pos+1] = uchar(255*val.g);
        data[pos+2] = uchar(255*val.b);
      }
    }

    image.loadDynamicImage(data, mImpl->width, mImpl->height, 1, PF_BYTE_RGB, true);
  }



  void SplattingManager::createBaseTexture(Image& image, size_t width, size_t height,
    ImageList textures, float repeatX, float repeatZ)
  {
    if (textures.size() > mImpl->numTextures)
      OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Given more textures than texture channels available.", "ET::SplattingManager::createBaseTexture");

    // first resize the textures according to the desired output size and the repeat values
    ushort scaleWidth = (ushort) (width / repeatX);
    ushort scaleHeight = (ushort) (height / repeatZ);
    for (ImageList::iterator it = textures.begin(); it != textures.end(); ++it)
      it->resize(scaleWidth, scaleHeight);

    // create the buffer to hold our generated base texture
    uchar* data = new uchar[width*height*3];
    size_t pos = 0;
    for (size_t y = 0; y < height; ++y)
    {
      for (size_t x = 0; x < width; ++x)
      {
        ColourValue val (0,0,0);
        int texX = (int) (x % scaleWidth);
        int texY = (int) (y % scaleHeight);
        for (size_t t = 0; t < textures.size(); ++t)
        {
          // get interpolated part of this texture at the current pixel
          float weight = mImpl->interpolateWeight(x, y, width, height, t);
          // get colour value of the texture image
          ColourValue col = textures[t].getColourAt(texX, texY, 0);
          // add to the pixel colour level
          val += weight*col;
        }

        // write colour to our buffer
        data[pos+0] = uchar(255*val.r);
        data[pos+1] = uchar(255*val.g);
        data[pos+2] = uchar(255*val.b);
        pos += 3;
      }
    }

    image.loadDynamicImage(data, width, height, 1, PF_BYTE_RGB, true);
  }


  Image createMinimap(const Image& colourMap, const Image& lightMap)
  {
    if (colourMap.getWidth() != lightMap.getWidth() || colourMap.getHeight() != lightMap.getHeight())
      OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Images must have the same dimensions.", __FUNCTION__);

    uchar* data = new uchar[colourMap.getWidth()*colourMap.getHeight()*3];

    for (size_t y = 0; y < colourMap.getWidth(); ++y)
    {
      for (size_t x = 0; x < colourMap.getHeight(); ++x)
      {
        ColourValue val = const_cast<Image&>(colourMap).getColourAt((uint)x, (uint)y, 0) * const_cast<Image&>(lightMap).getColourAt((uint)x, (uint)y, 0);
        size_t pos = (x + y*colourMap.getWidth()) * 3;
        data[pos+0] = uchar(255*val.r);
        data[pos+1] = uchar(255*val.g);
        data[pos+2] = uchar(255*val.b);
      }
    }

    Image image;
    image.loadDynamicImage(data, colourMap.getWidth(), colourMap.getHeight(), 1, PF_BYTE_RGB, true);
    return image;
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -