JD2022-TU1/main/tools/legacy/TexturePacker/AnimTexPacker/Patch.h

335 lines
13 KiB
C++

#ifndef _ITF_ANIMTEXPACKER_PATCH_H_
#define _ITF_ANIMTEXPACKER_PATCH_H_
#ifndef _ITF_PACKEDTEXTUREAREA_H_
#include "AnimTexPacker/PackedTextureArea.h"
#endif
#ifndef _ITF_TRANSFORM_H_
#include "core/math/transform.h"
#endif //_ITF_TRANSFORM_H_
#ifndef _ITF_BV_AABB_H_
#include "core/boundingvolume/AABB.h"
#endif //_ITF_BV_AABB_H_
#pragma warning(push)
#pragma warning(disable : 4244 4127 4512)
#include <nvcore/StrLib.h>
#include <nvcore/StdStream.h>
#include <nvimage/Image.h>
#include <nvmath/Color.h>
#include <nvimage/DirectDrawSurface.h>
#include <nvimage/ImageIO.h>
#include <nvtt/nvtt.h>
// NVIDIA has the bad idea to use defines to replace fcts, it's failing compilation
#undef sqrt
#undef sqrtf
#undef acos
#undef acosf
#undef asin
#undef asinf
#pragma warning(pop)
#ifndef ITF_GFX_MATERIAL_H_
#include "engine/display/material/GFXMaterial.h"
#endif //ITF_GFX_MATERIAL_H_
namespace ITF
{
class AnimBone;
class AnimTemplate;
class AnimSkeleton;
class AnimPatch;
class AnimPatchPoint;
class AnimPatchBank;
#define PATH_HDIV_DEF 2
namespace AnimTexPacker
{
struct ImageTextureMode
{
nv::Image m_image;
TextureSetSubID m_mode;
};
///////////////////////////////////////////////////////////////////////////////////////////
class ChainedBones
{
public:
SafeArray<AnimBone*> m_AnimBones;
};
///////////////////////////////////////////////////////////////////////////////////////////
class BoneExtent
{
public:
BoneExtent() {initEmpty();}
void initEmpty()
{
m_worldExtent.setMin(Vec2d(1,1));
m_worldExtent.setMax(Vec2d(0,0));
m_uvExtent.setMin(Vec2d(1,1));
m_uvExtent.setMax(Vec2d(0,0));
}
void grow(const Vec2d &_xy, const Vec2d &_uv)
{
if (m_worldExtent.isValid())
m_worldExtent.grow(_xy);
else
m_worldExtent = AABB(_xy,_xy);
if (m_uvExtent.isValid())
m_uvExtent.grow(_uv);
else
m_uvExtent = AABB(_uv,_uv);
}
AABB m_worldExtent, m_uvExtent;
};
class BoneMaxSize
{
public:
BoneMaxSize() {initEmpty();}
void initEmpty() { m_worldSize= AABB(Vec2d(0,0)); m_uvSize = AABB(Vec2d(0,0)); }
void grow(const Vec2d &_worldSize, const Vec2d &_uvSize)
{
m_worldSize.grow(_worldSize);
m_uvSize.grow(_uvSize);
}
f32 getMaxWorldSize() const {return Max(m_worldSize.getMax().x(), m_worldSize.getMax().y());}
AABB m_worldSize;
AABB m_uvSize;
};
///////////////////////////////////////////////////////////////////////////////////////////
///A patch : closed shape containing a texture. More or less an AnimTemplate+texture data+placement, but only 1 independent shape if bone is cut
class Patch
{
public:
Patch() :
m_UVBox(0,0,0,0)
, m_finalPos(0,0,0,0)
, m_subImageWidth(0)
, m_subImageHeight(0)
, m_animTemplate(NULL)
, m_initialImageWidth(0)
, m_initialImageHeight(0)
, m_skeleton(NULL)
, m_sourceOfAlias(NULL)
, m_uvModified(bfalse)
, m_angle(0.f)
, m_widthSampling(0)
, m_heightSampling(0)
{
static int currentSerial=0;
m_serialNumber = currentSerial;
m_uvlocalToRotatedLocalTransform.setIdentity();
m_imageStretchTransform.setIdentity();
currentSerial++;
}
Patch(const Patch&) {ITF_ASSERT(bfalse);}
Patch& operator=(const Patch&) {ITF_ASSERT(bfalse);return *this;}
~Patch();
///////////////////////////////////////////////////////////////////////////////////////////
void setAliasOf(Patch *_sourceOfAlias) {m_sourceOfAlias = _sourceOfAlias;}
Patch *getSourceOfAlias() const {return m_sourceOfAlias;}
///////////////////////////////////////////////////////////////////////////////////////////
const BoxI &getUVBox() const {return m_UVBox;}
///////////////////////////////////////////////////////////////////////////////////////////
void setFinalPos(const BoxI &_finalBox, const Transform2d &_uvTransform);
///////////////////////////////////////////////////////////////////////////////////////////
void setFinalPosFromAlias();
///////////////////////////////////////////////////////////////////////////////////////////
const StringID &getTemplateID() const {return m_templateID;}
///////////////////////////////////////////////////////////////////////////////////////////
const Path& getImagePath() const {return m_diffuseImagePath;}
const StringID & getBankID() const {return m_bankID;}
///////////////////////////////////////////////////////////////////////////////////////////
int computePlacementHeuristic(PackedTextureArea *_area, BoxI &b);
///////////////////////////////////////////////////////////////////////////////////////////
bbool Place(PackedTextureArea *_area, BoxI &b, bbool &_rotated, Transform2d &_subImageRotation);
///////////////////////////////////////////////////////////////////////////////////////////
bbool isEqual(const Patch *_other);
///////////////////////////////////////////////////////////////////////////////////////////
///Initialize from animation data
void initialize(const StringID &_bankID, const StringID &_templateID, AnimTemplate *_animTemplate, ChainedBones &_chainedBones, ITF_VECTOR<ImageTextureMode> &_imageTab, const Path &_imagePath, AnimSkeleton *_skeleton);
int getUVBoundingWidth() const {return m_UVBox.maxx-m_UVBox.minx+1;}
int getUVBoundingHeight() const {return m_UVBox.maxy-m_UVBox.miny+1;}
u32 getSubImageWidth() const {return m_subImageWidth;}
u32 getSubImageHeight() const {return m_subImageHeight;}
///////////////////////////////////////////////////////////////////////////////////////////
void extractPixels(nv::Image &_image, u32 idx);
const SafeArray<u32> &getBoneIndices() const {return m_boneIndices;}
const ITF_VECTOR<StringID> &getBoneIDs() const {return m_boneIDs;}
///////////////////////////////////////////////////////////////////////////////////////////
void blitToFinalPos(nv::Image &_destImage, i32 xOffset, i32 yOffset, u32 _idx);
///////////////////////////////////////////////////////////////////////////////////////////
void growPatchMaxSize(const BoneMaxSize& _toAdd );
///////////////////////////////////////////////////////////////////////////////////////////
const BoneMaxSize &getPatchMaxSize() const;
nv::Color32 getPixel(int _x, int _y, u32 idx) const
{
int w = (int)getSubImageWidth();
ITF_ASSERT(_x>=0 && _y>=0 && _x<w && _y<(int)getSubImageHeight());
return m_pixelsTab[idx][_x+_y*w];
}
nv::Color32 getPixel_WithBorder(int _x, int _y, u32 idx) const
{
int w = (int)getSubImageWidth();
if(_x>=0 && _y>=0 && _x<w && _y<(int)getSubImageHeight())
return m_pixelsTab[idx][_x+_y*w];
else
return nv::Color32(0,0,0,0);
}
///////////////////////////////////////////////////////////////////////////////////////////
//void resizeTexture(int _newSize);
///////////////////////////////////////////////////////////////////////////////////////////
nv::Color32 samplePixel_Linear(f32 _x, f32 _y, u32 _idx);
///////////////////////////////////////////////////////////////////////////////////////////
void modifyUVs(int mapWidth, int mapHeight, ITF_SET<AnimPatchPoint*> &_alreadyProcessedPoints);
///////////////////////////////////////////////////////////////////////////////////////////
AnimTemplate * getAnimTemplate( ) { return m_animTemplate; }
///////////////////////////////////////////////////////////////////////////////////////////
AnimSkeleton * getAnimSkeleton( ) { return m_skeleton; }
int getInitialImageWidth ( ) { return m_initialImageWidth; }
int getInitialImageHeight ( ) { return m_initialImageHeight; }
const ITF_VECTOR<Vec2d> & getPointList() { return m_pointList; }
void setAngle(f32 _angle) { m_angle = _angle; }
const Vec2d & getProcessDelta() { return m_processDelta; }
void setSample(u32 _width, u32 _height, const SafeArray<u32> & _sampling );
static void setSaveInFile(const Path & _fileModel) { m_saveInFile = _fileModel; }
static u32 s_patchHdiv;
private:
///////////////////////////////////////////////////////////////////////////////////////////
bbool computePatchUVAABB(AnimPatch *_patch, AABB &UVs, nv::Image &_image, Vec2d *_ptList);
///////////////////////////////////////////////////////////////////////////////////////////
///compute uv aabb from animation data
void computeUVAABB(AnimTemplate *_template, ChainedBones &_chainedBones, nv::Image &_image);
///////////////////////////////////////////////////////////////////////////////////////////
static Path m_saveInFile;
Path getPixelsTabFileName(u32 _idx);
nv::Color32 * savePixelsTab(nv::Color32 * _pixelTab, u32 _idx);
nv::Color32 * loadPixelsTab(nv::Color32 * _pixelTab, u32 _idx);
AnimTemplate * m_animTemplate;
StringID m_bankID;
StringID m_templateID;
BoxI m_UVBox;
BoxI m_finalPos;
Vec2d m_processDelta;
int m_subImageWidth;
int m_subImageHeight;
SafeArray<nv::Color32 *> m_pixelsTab;
Path m_diffuseImagePath;
int m_serialNumber;
SafeArray<u32> m_boneIndices;
ITF_VECTOR<StringID> m_boneIDs;
bbool m_uvModified;
static const u32 m_PatchsDegree = 4;
static const u32 m_PatchsNumberOfCurves = 2;
BoneMaxSize m_boneMaxSize;
AnimSkeleton *m_skeleton;
int m_initialImageWidth;
int m_initialImageHeight;
Patch *m_sourceOfAlias;
//Transforms the m_pPixels in UV coordinates in the same coordinate frame, but with possibly a rotation (eg a 90 deg)
Transform2d m_uvlocalToRotatedLocalTransform, m_imageStretchTransform;
f32 m_angle;
ITF_VECTOR<Vec2d> m_pointList;
SafeArray<u32> m_sampling;
u32 m_widthSampling;
u32 m_heightSampling;
};
///////////////////////////////////////////////////////////////////////////////////////////
/// List of patches
class PatchList
{
public:
static u32 CURRENT_SAMPLING;
Path m_patchImagePath;
AnimPatchBank * m_patchBank;
ITF_VECTOR<StringID> m_usedPatches;
ITF_LIST<Patch*> m_patches;
StringID m_bankName;
u32 m_imgMask;
u32 m_imgUseAlphaMask;
u32 m_hdDownscaleMask;
///////////////////////////////////////////////////////////////////////////////////////////
PatchList()
{
m_patchBank = NULL;
}
///////////////////////////////////////////////////////////////////////////////////////////
void destroy(void)
{
ITF_LIST<Patch*>::iterator iter;
for (iter=m_patches.begin(); iter!=m_patches.end(); iter++)
{
delete *iter;
}
m_patches.clear();
m_usedPatches.clear();
}
};
}
}
#endif