#ifndef Ptexture_h
#define Ptexture_h
#if defined(_WIN32) || defined(_WINDOWS) || defined(_MSC_VER)
# ifndef PTEX_STATIC
# ifdef PTEX_EXPORTS
# define PTEXAPI __declspec(dllexport)
# else
# define PTEXAPI __declspec(dllimport)
# endif
# else
# define PTEXAPI
# endif
#else
# define PTEXAPI
# ifndef DOXYGEN
# define PTEX_USE_STDSTRING
# endif
#endif
#include "PtexInt.h"
#include <ostream>
#define PtexAPIVersion 2
#define PtexFileMajorVersion 1
#define PtexFileMinorVersion 3
struct Ptex {
enum MeshType {
mt_triangle,
mt_quad
};
enum DataType {
dt_uint8,
dt_uint16,
dt_half,
dt_float
};
enum BorderMode {
m_clamp,
m_black,
m_periodic
};
enum EdgeId {
e_bottom,
e_right,
e_top,
e_left
};
enum MetaDataType {
mdt_string,
mdt_int8,
mdt_int16,
mdt_int32,
mdt_float,
mdt_double
};
PTEXAPI static const char* MeshTypeName(MeshType mt);
PTEXAPI static const char* DataTypeName(DataType dt);
PTEXAPI static const char* BorderModeName(BorderMode m);
PTEXAPI static const char* EdgeIdName(EdgeId eid);
PTEXAPI static const char* MetaDataTypeName(MetaDataType mdt);
static int DataSize(DataType dt) {
static const int sizes[] = { 1,2,2,4 };
return sizes[dt];
}
static double OneValue(DataType dt) {
static const double one[] = { 255.0, 65535.0, 1.0, 1.0 };
return one[dt];
}
static double OneValueInv(DataType dt) {
static const double one[] = { 1.0/255.0, 1.0/65535.0, 1.0, 1.0 };
return one[dt];
}
PTEXAPI static void ConvertToFloat(float* dst, const void* src,
Ptex::DataType dt, int numChannels);
PTEXAPI static void ConvertFromFloat(void* dst, const float* src,
Ptex::DataType dt, int numChannels);
struct Res {
int8_t ulog2;
int8_t vlog2;
Res() : ulog2(0), vlog2(0) {}
Res(int8_t ulog2, int8_t vlog2) : ulog2(ulog2), vlog2(vlog2) {}
Res(uint16_t value) { val() = value; }
int u() const { return 1<<(unsigned)ulog2; }
int v() const { return 1<<(unsigned)vlog2; }
uint16_t& val() { return *(uint16_t*)this; }
const uint16_t& val() const { return *(uint16_t*)this; }
int size() const { return u() * v(); }
bool operator==(const Res& r) const { return val() == r.val(); }
bool operator!=(const Res& r) const { return val() != r.val(); }
bool operator>=(const Res& r) const { return ulog2 >= r.ulog2 && vlog2 >= r.vlog2; }
Res swappeduv() const { return Res(vlog2, ulog2); }
void swapuv() { *this = swappeduv(); }
void clamp(const Res& r) {
if (ulog2 > r.ulog2) ulog2 = r.ulog2;
if (vlog2 > r.vlog2) vlog2 = r.vlog2;
}
int ntilesu(Res tileres) const { return 1<<(ulog2-tileres.ulog2); }
int ntilesv(Res tileres) const { return 1<<(vlog2-tileres.vlog2); }
int ntiles(Res tileres) const { return ntilesu(tileres) * ntilesv(tileres); }
};
struct FaceInfo {
Res res;
uint8_t adjedges;
uint8_t flags;
int32_t adjfaces[4];
FaceInfo() : res(), adjedges(0), flags(0)
{
adjfaces[0] = adjfaces[1] = adjfaces[2] = adjfaces[3] = -1;
}
FaceInfo(Res res) : res(res), adjedges(0), flags(0)
{
adjfaces[0] = adjfaces[1] = adjfaces[2] = adjfaces[3] = -1;
}
FaceInfo(Res res, int adjfaces[4], int adjedges[4], bool isSubface=false)
: res(res), flags(isSubface ? flag_subface : 0)
{
setadjfaces(adjfaces[0], adjfaces[1], adjfaces[2], adjfaces[3]);
setadjedges(adjedges[0], adjedges[1], adjedges[2], adjedges[3]);
}
EdgeId adjedge(int eid) const { return EdgeId((adjedges >> (2*eid)) & 3); }
int adjface(int eid) const { return adjfaces[eid]; }
bool isConstant() const { return (flags & flag_constant) != 0; }
bool isNeighborhoodConstant() const { return (flags & flag_nbconstant) != 0; }
bool hasEdits() const { return (flags & flag_hasedits) != 0; }
bool isSubface() const { return (flags & flag_subface) != 0; }
void setadjfaces(int f0, int f1, int f2, int f3)
{ adjfaces[0] = f0, adjfaces[1] = f1, adjfaces[2] = f2; adjfaces[3] = f3; }
void setadjedges(int e0, int e1, int e2, int e3)
{ adjedges = (e0&3) | ((e1&3)<<2) | ((e2&3)<<4) | ((e3&3)<<6); }
enum { flag_constant = 1, flag_hasedits = 2, flag_nbconstant = 4, flag_subface = 8 };
};
#ifdef PTEX_USE_STDSTRING
typedef std::string String;
#else
class String
{
public:
String() : _str(0) {}
String(const String& str) : _str(0) { *this = str; }
PTEXAPI ~String();
PTEXAPI String& operator=(const char* str);
String& operator=(const String& str) { *this = str._str; return *this; }
const char* c_str() const { return _str ? _str : ""; }
bool empty() const { return _str == 0; }
private:
char* _str;
};
#endif
}
#ifndef DOXYGEN
;
#endif
#ifndef PTEX_USE_STDSTRING
std::ostream& operator << (std::ostream& stream, const Ptex::String& str);
#endif
class PtexMetaData {
protected:
virtual ~PtexMetaData() {}
public:
virtual void release() = 0;
virtual int numKeys() = 0;
virtual void getKey(int n, const char*& key, Ptex::MetaDataType& type) = 0;
virtual void getValue(const char* key, const char*& value) = 0;
virtual void getValue(const char* key, const int8_t*& value, int& count) = 0;
virtual void getValue(const char* key, const int16_t*& value, int& count) = 0;
virtual void getValue(const char* key, const int32_t*& value, int& count) = 0;
virtual void getValue(const char* key, const float*& value, int& count) = 0;
virtual void getValue(const char* key, const double*& value, int& count) = 0;
};
class PtexFaceData {
protected:
virtual ~PtexFaceData() {}
public:
virtual void release() = 0;
virtual bool isConstant() = 0;
virtual Ptex::Res res() = 0;
virtual void getPixel(int u, int v, void* result) = 0;
virtual void* getData() = 0;
virtual bool isTiled() = 0;
virtual Ptex::Res tileRes() = 0;
virtual PtexFaceData* getTile(int tile) = 0;
};
class PtexTexture {
protected:
virtual ~PtexTexture() {}
public:
PTEXAPI static PtexTexture* open(const char* path, Ptex::String& error, bool premultiply=0);
virtual void release() = 0;
virtual const char* path() = 0;
virtual Ptex::MeshType meshType() = 0;
virtual Ptex::DataType dataType() = 0;
virtual Ptex::BorderMode uBorderMode() = 0;
virtual Ptex::BorderMode vBorderMode() = 0;
virtual int alphaChannel() = 0;
virtual int numChannels() = 0;
virtual int numFaces() = 0;
virtual bool hasEdits() = 0;
virtual bool hasMipMaps() = 0;
virtual PtexMetaData* getMetaData() = 0;
virtual const Ptex::FaceInfo& getFaceInfo(int faceid) = 0;
virtual void getData(int faceid, void* buffer, int stride) = 0;
virtual void getData(int faceid, void* buffer, int stride, Ptex::Res res) = 0;
virtual PtexFaceData* getData(int faceid) = 0;
virtual PtexFaceData* getData(int faceid, Ptex::Res res) = 0;
virtual void getPixel(int faceid, int u, int v,
float* result, int firstchan, int nchannels) = 0;
virtual void getPixel(int faceid, int u, int v,
float* result, int firstchan, int nchannels,
Ptex::Res res) = 0;
};
class PtexInputHandler {
protected:
virtual ~PtexInputHandler() {}
public:
typedef void* Handle;
virtual Handle open(const char* path) = 0;
virtual void seek(Handle handle, int64_t pos) = 0;
virtual size_t read(void* buffer, size_t size, Handle handle) = 0;
virtual bool close(Handle handle) = 0;
virtual const char* lastError() = 0;
};
class PtexCache {
protected:
virtual ~PtexCache() {}
public:
PTEXAPI static PtexCache* create(int maxFiles=0,
int maxMem=0,
bool premultiply=false,
PtexInputHandler* handler=0);
virtual void release() = 0;
virtual void setSearchPath(const char* path) = 0;
virtual const char* getSearchPath() = 0;
virtual PtexTexture* get(const char* path, Ptex::String& error) = 0;
virtual void purge(PtexTexture* texture) = 0;
virtual void purge(const char* path) = 0;
virtual void purgeAll() = 0;
};
class PtexWriter {
protected:
virtual ~PtexWriter() {}
public:
PTEXAPI
static PtexWriter* open(const char* path,
Ptex::MeshType mt, Ptex::DataType dt,
int nchannels, int alphachan, int nfaces,
Ptex::String& error, bool genmipmaps=true);
PTEXAPI
static PtexWriter* edit(const char* path, bool incremental,
Ptex::MeshType mt, Ptex::DataType dt,
int nchannels, int alphachan, int nfaces,
Ptex::String& error, bool genmipmaps=true);
PTEXAPI
static bool applyEdits(const char* path, Ptex::String& error);
virtual void release() = 0;
virtual void setBorderModes(Ptex::BorderMode uBorderMode, Ptex::BorderMode vBorderMode) = 0;
virtual void writeMeta(const char* key, const char* string) = 0;
virtual void writeMeta(const char* key, const int8_t* value, int count) = 0;
virtual void writeMeta(const char* key, const int16_t* value, int count) = 0;
virtual void writeMeta(const char* key, const int32_t* value, int count) = 0;
virtual void writeMeta(const char* key, const float* value, int count) = 0;
virtual void writeMeta(const char* key, const double* value, int count) = 0;
virtual void writeMeta(PtexMetaData* data) = 0;
virtual bool writeFace(int faceid, const Ptex::FaceInfo& info, const void* data, int stride=0) = 0;
virtual bool writeConstantFace(int faceid, const Ptex::FaceInfo& info, const void* data) = 0;
virtual bool close(Ptex::String& error) = 0;
#if NEW_API
virtual bool writeFaceReduction(int faceid, const Ptex::Res& res, const void* data, int stride=0) = 0;
virtual bool writeConstantFaceReduction(int faceid, const Ptex::Res& res, const void* data) = 0;
#endif
};
class PtexFilter {
protected:
virtual ~PtexFilter() {};
public:
enum FilterType {
f_point,
f_bilinear,
f_box,
f_gaussian,
f_bicubic,
f_bspline,
f_catmullrom,
f_mitchell
};
struct Options {
int __structSize;
FilterType filter;
bool lerp;
float sharpness;
Options(FilterType filter=f_box, bool lerp=0, float sharpness=0) :
__structSize(sizeof(Options)),
filter(filter), lerp(lerp), sharpness(sharpness) {}
};
PTEXAPI static PtexFilter* getFilter(PtexTexture* tx, const Options& opts);
virtual void release() = 0;
virtual void eval(float* result, int firstchan, int nchannels,
int faceid, float u, float v, float uw1, float vw1, float uw2, float vw2,
float width=1, float blur=0) = 0;
};
template <class T> class PtexPtr {
T* _ptr;
public:
PtexPtr(T* ptr=0) : _ptr(ptr) {}
~PtexPtr() { if (_ptr) _ptr->release(); }
operator T* () { return _ptr; }
T* operator-> () { return _ptr; }
T* get() { return _ptr; }
private:
PtexPtr(const PtexPtr& p);
void operator= (PtexPtr& p);
};
#endif