Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/textureutils.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzLib includes
Toshihiro Shimizu 890ddd
#include "toonz/txshleveltypes.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshsimplelevel.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshchildlevel.h"
Toshihiro Shimizu 890ddd
#include "toonz/txsheet.h"
Toshihiro Shimizu 890ddd
#include "toonz/tstageobjecttree.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshcell.h"
Toshihiro Shimizu 890ddd
#include "toonz/tstageobject.h"
Toshihiro Shimizu 890ddd
#include "toonz/stage.h"
Toshihiro Shimizu 890ddd
#include "toonz/toonzscene.h"
Toshihiro Shimizu 890ddd
#include "toonz/imagemanager.h"
Toshihiro Shimizu 890ddd
#include "imagebuilders.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tpalette.h"
Toshihiro Shimizu 890ddd
#include "tconvert.h"
Toshihiro Shimizu 890ddd
#include "ttoonzimage.h"
Toshihiro Shimizu 890ddd
#include "trop.h"
Toshihiro Shimizu 890ddd
#include "tropcm.h"
Toshihiro Shimizu 890ddd
#include "tgl.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************************
Toshihiro Shimizu 890ddd
//    TXshSimpleLevel Texture Utilities  locals
Toshihiro Shimizu 890ddd
//********************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
TRasterImageP convert32(const TImageP &img) {
Shinya Kitaoka 120a6e
  struct locals {
Shinya Kitaoka 120a6e
    static TRasterImageP depremultiplied(const TRasterImageP &ri) {
Shinya Kitaoka 120a6e
      assert(ri->getRaster());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TRop::depremultiply(ri->getRaster());
Shinya Kitaoka 120a6e
      return ri;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  };  // locals
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (TRasterImageP ri = img) {
Shinya Kitaoka 120a6e
    TRasterP ras(ri->getRaster());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRaster32P ras32;
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      if (TRaster32P(ras))
Shinya Kitaoka 120a6e
        ras32 = ras->clone();
Shinya Kitaoka 120a6e
      else {
Shinya Kitaoka 120a6e
        ras32 = TRaster32P(ras->getSize());
Shinya Kitaoka 120a6e
        TRop::convert(ras32, ras);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPointD dpi;
Shinya Kitaoka 120a6e
    ri->getDpi(dpi.x, dpi.y);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRasterImageP ri32(ras32);
Shinya Kitaoka 120a6e
    ri32->setDpi(dpi.x, dpi.y);
Shinya Kitaoka 120a6e
    ri32->setSubsampling(ri->getSubsampling());
Shinya Kitaoka 120a6e
    ri32->setOffset(ri->getOffset());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    return locals::depremultiplied(ri32);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (TToonzImageP ti = img) {
Shinya Kitaoka 120a6e
    TRasterCM32P rasCM32(ti->getRaster());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRaster32P ras32(rasCM32->getSize());
Shinya Kitaoka 120a6e
    TRop::convert(ras32, rasCM32, ti->getPalette());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPointD dpi;
Shinya Kitaoka 120a6e
    ti->getDpi(dpi.x, dpi.y);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRasterImageP ri32(ras32);
Shinya Kitaoka 120a6e
    ri32->setDpi(dpi.x, dpi.y);
Shinya Kitaoka 120a6e
    ri32->setSubsampling(ti->getSubsampling());
Shinya Kitaoka 120a6e
    ri32->setOffset(ti->getOffset());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    return locals::depremultiplied(ri32);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return TRasterImageP();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TRasterImageP getTexture(const TXshSimpleLevel *sl, const TFrameId &fid,
Shinya Kitaoka 120a6e
                         int subsampling) {
Shinya Kitaoka 120a6e
  if (sl->getType() != PLI_XSHLEVEL) {
Shinya Kitaoka 120a6e
    TImageP texImg =
Shinya Kitaoka 120a6e
        sl->getFrame(fid, ImageManager::dontPutInCache, subsampling);
Shinya Kitaoka 120a6e
    return convert32(texImg);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Vector case
Shinya Kitaoka 120a6e
  std::string id = sl->getImageId(fid) + "_rasterized";
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ImageLoader::BuildExtData extData(sl, fid);
Shinya Kitaoka 120a6e
  TRasterImageP ri(ImageManager::instance()->getImage(
Shinya Kitaoka 120a6e
      id, ImageManager::dontPutInCache, &extData));
Shinya Kitaoka 6f0974
Shinya Kitaoka 120a6e
  return ri;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************************
Toshihiro Shimizu 890ddd
//    TXshSimpleLevel Texture Utilities  implementation
Toshihiro Shimizu 890ddd
//********************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DrawableTextureDataP texture_utils::getTextureData(const TXshSimpleLevel *sl,
Shinya Kitaoka 120a6e
                                                   const TFrameId &fid,
Shinya Kitaoka 120a6e
                                                   int subsampling) {
Shinya Kitaoka 120a6e
  const std::string &texId = sl->getImageId(fid);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Now, we must associate a texture
Shinya Kitaoka 120a6e
  DrawableTextureDataP data(
Shinya Kitaoka 120a6e
      TTexturesStorage::instance()->getTextureData(texId));
Shinya Kitaoka 120a6e
  if (data) return data;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // There was no associated texture. We must bind the texture and repeat
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // First, retrieve the image to be used as texture
Shinya Kitaoka 120a6e
  TRasterImageP ri(::getTexture(sl, fid, subsampling));
Shinya Kitaoka 120a6e
  if (!ri) return DrawableTextureDataP();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRaster32P ras(ri->getRaster());
Shinya Kitaoka 120a6e
  assert(ras);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRectD geom(0, 0, ras->getLx(), ras->getLy());
Shinya Kitaoka 120a6e
  geom = TScale(ri->getSubsampling()) *
Shinya Kitaoka 120a6e
         TTranslation(convert(ri->getOffset()) - ras->getCenterD()) * geom;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return TTexturesStorage::instance()->loadTexture(texId, ras, geom);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void texture_utils::invalidateTexture(const TXshSimpleLevel *sl,
Shinya Kitaoka 120a6e
                                      const TFrameId &fid) {
Shinya Kitaoka 120a6e
  const std::string &texId = sl->getImageId(fid);
Shinya Kitaoka 120a6e
  TTexturesStorage::instance()->unloadTexture(texId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void texture_utils::invalidateTextures(const TXshSimpleLevel *sl) {
Shinya Kitaoka 120a6e
  int f, fCount = sl->getFrameCount();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (f = 0; f != fCount; ++f) invalidateTexture(sl, sl->getFrameId(f));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************************
Toshihiro Shimizu 890ddd
//    TXsheet Texture Utilities  locals
Toshihiro Shimizu 890ddd
//********************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::string getImageId(const TXsheet *xsh, int frame) {
Shinya Kitaoka 120a6e
  return "X" + std::to_string(xsh->id()) + "_" + std::to_string(frame);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************************
Toshihiro Shimizu 890ddd
//    TXsheet Texture Utilities  implementation
Toshihiro Shimizu 890ddd
//********************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DrawableTextureDataP texture_utils::getTextureData(const TXsheet *xsh,
Shinya Kitaoka 120a6e
                                                   int frame) {
Shinya Kitaoka 120a6e
  // Check if an xsheet texture already exists
Shinya Kitaoka 120a6e
  const std::string &texId = ::getImageId(xsh, frame);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  DrawableTextureDataP data(
Shinya Kitaoka 120a6e
      TTexturesStorage::instance()->getTextureData(texId));
Shinya Kitaoka 120a6e
  if (data) return data;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // No available texture - we must build and load it
Shinya Kitaoka 120a6e
  TRaster32P tex(
Shinya Kitaoka 120a6e
      1024,
Shinya Kitaoka 120a6e
      1024);  // Fixed texture size. It's the same that currently happens with
Shinya Kitaoka 120a6e
              // vector images' textures - and justified since this is camstand
Shinya Kitaoka 120a6e
  // mode, and besides we want to make sure that textures are limited.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Retrieve the sub-xsheet bbox (world coordinates of the sub-xsheet)
Shinya Kitaoka 120a6e
  TRectD bbox(xsh->getBBox(frame));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Since xsh represents a sub-xsheet, its camera affine must be applied
Shinya Kitaoka 120a6e
  const TAffine &cameraAff =
Shinya Kitaoka 120a6e
      xsh->getPlacement(xsh->getStageObjectTree()->getCurrentCameraId(), frame);
Shinya Kitaoka 120a6e
  bbox = (cameraAff.inv() * bbox).enlarge(1.0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Render the xsheet on the specified bbox
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // The call below will change context (I know, it's a shame :( )
Shinya Kitaoka 120a6e
  TGlContext currentContext = tglGetCurrentContext();
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    tglDoneCurrent(currentContext);
Shinya Kitaoka 120a6e
    xsh->getScene()->renderFrame(tex, frame, xsh, bbox, TAffine());
Shinya Kitaoka 120a6e
    tglMakeCurrent(currentContext);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRop::depremultiply(tex);  // Stored textures are rendered nonpremultiplied
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Store the texture for future retrieval
Shinya Kitaoka 120a6e
  return TTexturesStorage::instance()->loadTexture(texId, tex, bbox);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void texture_utils::invalidateTexture(const TXsheet *xsh, int frame) {
Shinya Kitaoka 120a6e
  const std::string &texId = ::getImageId(xsh, frame);
Shinya Kitaoka 120a6e
  TTexturesStorage::instance()->unloadTexture(texId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void texture_utils::invalidateTextures(const TXsheet *xsh) {
Shinya Kitaoka 120a6e
  int f, fCount = xsh->getFrameCount();
Shinya Kitaoka 120a6e
  for (f = 0; f != fCount; ++f) invalidateTexture(xsh, f);
Toshihiro Shimizu 890ddd
}