[Bf-blender-cvs] [4cc26f4] cycles-ptex-24: WIP Ptex texture packing
Nicholas Bishop
noreply at git.blender.org
Fri Jan 30 18:00:20 CET 2015
Commit: 4cc26f4fbe3e6b2f45d6deaf6e567f685abf6b9a
Author: Nicholas Bishop
Date: Fri Jan 16 12:27:41 2015 +0100
Branches: cycles-ptex-24
https://developer.blender.org/rB4cc26f4fbe3e6b2f45d6deaf6e567f685abf6b9a
WIP Ptex texture packing
===================================================================
M extern/ptex/CMakeLists.txt
A extern/ptex/bl_ptex.h
A extern/ptex/pack.cpp
A extern/ptex/ptex_packed_layout.h
===================================================================
diff --git a/extern/ptex/CMakeLists.txt b/extern/ptex/CMakeLists.txt
index 7e7bcd0..0eda505 100644
--- a/extern/ptex/CMakeLists.txt
+++ b/extern/ptex/CMakeLists.txt
@@ -24,12 +24,16 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
+ .
)
set(INC_SYS
)
set(SRC
+ bl_ptex.h
+ pack.cpp
+
src/ptex/PtexCache.h
src/ptex/PtexDict.h
src/ptex/PtexHalf.h
diff --git a/extern/ptex/bl_ptex.h b/extern/ptex/bl_ptex.h
new file mode 100644
index 0000000..fbfc32c
--- /dev/null
+++ b/extern/ptex/bl_ptex.h
@@ -0,0 +1,74 @@
+#ifndef __BL_PTEX_H__
+#define __BL_PTEX_H__
+
+#ifdef __cplusplus
+/* Silence warning */
+# define NEW_API 0
+
+# include "src/ptex/Ptexture.h"
+
+class PtexCache;
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PtexPackedTexture;
+struct PtexCacheHandle;
+
+struct PtexTableElement {
+ int co[2];
+ int res[2];
+};
+
+struct PtexPackedLayout;
+struct PtexPackedLayout *ptex_packed_layout_new(int count);
+void ptex_packed_layout_add(struct PtexPackedLayout *layout,
+ int u_res, int v_res, int id);
+void ptex_packed_layout_finalize(struct PtexPackedLayout *layout);
+void ptex_packed_layout_delete(struct PtexPackedLayout *layout);
+
+struct PtexCacheHandle *ptex_cache_new(void);
+void ptex_cache_delete(struct PtexCacheHandle *ptex_cache_handle);
+
+struct PtexPackedTexture *ptex_packed_texture_new(void);
+
+void ptex_packed_texture_delete(struct PtexPackedTexture *ppt);
+
+bool ptex_packed_texture_fill(struct PtexPackedTexture *output,
+ const char *path,
+ const int width,
+ struct PtexCacheHandle *ptex_cache_handle);
+
+typedef void (*LoopDataFunc)(void *src, int index, void **texels,
+ int *u_rlog2, int *v_rlog2);
+
+bool ptex_packed_texture_from_layout(struct PtexPackedTexture *output,
+ struct PtexPackedLayout *layout,
+ LoopDataFunc loop_data,
+ void *loop_data_src,
+ const int num_loops,
+ // TODO, should use an enum for
+ // data_type
+ const int data_type,
+ const int num_channels,
+ const int alpha_channel);
+
+int ptex_packed_texture_width(const struct PtexPackedTexture *ppt);
+int ptex_packed_texture_height(const struct PtexPackedTexture *ppt);
+int ptex_packed_texture_bytes_per_texel(const struct PtexPackedTexture *ppt);
+int ptex_packed_texture_num_channels(const struct PtexPackedTexture *ppt);
+const void *ptex_packed_texture_texels(const struct PtexPackedTexture *ppt);
+int ptex_packed_texture_table_len(const struct PtexPackedTexture *ppt);
+
+const struct PtexTableElement *
+ptex_packed_texture_table_elem(const struct PtexPackedTexture *ppt,
+ const int index);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif
diff --git a/extern/ptex/pack.cpp b/extern/ptex/pack.cpp
new file mode 100644
index 0000000..2b9a8dd
--- /dev/null
+++ b/extern/ptex/pack.cpp
@@ -0,0 +1,795 @@
+#include "ptex_packed_layout.h"
+
+
+#include <OpenImageIO/imageio.h>
+OIIO_NAMESPACE_USING
+
+#include <cassert>
+#include <vector>
+
+#include "bl_ptex.h"
+
+// TODO, silly to copy utility classes...
+struct float2 {
+ float x, y;
+
+ void operator+=(const float2 &other)
+ {
+ x += other.x;
+ y += other.y;
+ }
+
+ float2 operator*(const float s) const
+ {
+ float2 result = {x * s, y * s};
+ return result;
+ }
+};
+
+static float2 make_float2(float x, float y)
+{
+ float2 f = {x, y};
+ return f;
+}
+
+// TODO, obviously not correct
+typedef unsigned int uint;
+typedef unsigned char uint8_t;
+
+PtexPackedLayout *ptex_packed_layout_new(const int count)
+{
+ return new PtexPackedLayout(count);
+}
+
+void ptex_packed_layout_add(PtexPackedLayout * const layout,
+ const int u_res, const int v_res,
+ const int id)
+{
+ layout->add_item(PtexPackedLayout::Item(u_res, v_res, id));
+}
+
+void ptex_packed_layout_finalize(PtexPackedLayout * const layout)
+{
+ layout->finalize();
+}
+
+void ptex_packed_layout_delete(PtexPackedLayout *layout)
+{
+ delete layout;
+}
+
+struct PtexPackedTexture {
+ PtexPackedTexture() : width(0), height(0) {}
+
+ class Cursor {
+ public:
+ Cursor(PtexPackedTexture &output, const int start_x,
+ const int start_y)
+ : output(output),
+ offset(output.calc_offset(start_x, start_y))
+ {
+ }
+
+ void set_increment(const int new_incr)
+ {
+ incr = new_incr;
+ }
+
+ void step()
+ {
+ offset += incr;
+ }
+
+ uint8_t *data() {
+ return output.data(offset);
+ }
+
+ private:
+ PtexPackedTexture &output;
+ int incr;
+ int offset;
+ };
+
+ int calc_offset(const int x, const int y) const
+ {
+ return (y * width + x) * bytes_per_texel;
+ }
+
+ uint8_t *data(const int pixel_index)
+ {
+ assert(pixel_index >= 0);
+ assert(pixel_index < texels.size() - num_channels);
+
+ return texels.data() + pixel_index;
+ }
+
+ void set_texel_type(const int channels, const Ptex::DataType dt)
+ {
+ num_channels = channels;
+ data_type = dt;
+ bytes_per_texel = channels * Ptex::DataSize(dt);
+ }
+
+ void resize(const int w, const int h)
+ {
+ width = w;
+ height = h;
+
+ dst_stride = width * bytes_per_texel;
+
+ texels.resize(width * height * bytes_per_texel);
+ }
+
+ // TODO: more privacy here
+
+ std::vector<uint8_t> texels;
+
+ std::vector<PtexTableElement> table;
+
+ uint width;
+ uint height;
+
+ int num_channels;
+
+ int bytes_per_texel;
+ int dst_stride;
+
+ void test_write() {
+ // Quick test to visually examine the packed output
+ const char *filename = "/tmp/packed.png";
+ ImageOutput *out = ImageOutput::create(filename);
+ if (out) {
+ ImageSpec spec(width, height, num_channels, TypeDesc::UINT8);
+ out->open(filename, spec);
+ out->write_image(TypeDesc::UINT8, texels.data());
+ std::cout << "ptex test written: " << filename << std::endl;
+ out->close();
+ }
+ }
+
+ Ptex::DataType data_type;
+};
+
+struct PtexEdgeIter {
+ /* Set up a texel iterator for one edge of a face
+ *
+ * face and edge_id: specify the edge being iterated over
+ *
+ * from_res: the resolution of a neighboring face, controls the
+ * distance to step each time next() is called; next()
+ * can be called up to `from_res` times.
+ *
+ * reverse: iterate over the edge backwards. In general this is
+ * `true` because adjacent face edges have (implicit)
+ * opposite directions.
+ */
+ PtexEdgeIter(PtexFaceData &face,
+ const Ptex::EdgeId edge_id,
+ const int from_res,
+ const bool reverse)
+ : face(face)
+ {
+ const Ptex::Res &res = face.res();
+
+ float u_res = res.u() - 1.0f;
+ float v_res = res.v() - 1.0f;
+ const float u_incr = (u_res + 1.0f) / (float)from_res;
+ const float v_incr = (v_res + 1.0f) / (float)from_res;
+
+ switch (edge_id) {
+ case Ptex::e_bottom:
+ if (reverse) {
+ pos = make_float2(u_res, 0);
+ incr = make_float2(-u_incr, 0);
+ }
+ else {
+ pos = make_float2(0, 0);
+ incr = make_float2(u_incr, 0);
+ }
+ break;
+
+ case Ptex::e_right:
+ if (reverse) {
+ pos = make_float2(u_res, v_res);
+ incr = make_float2(0, -v_incr);
+ }
+ else {
+ pos = make_float2(u_res, 0);
+ incr = make_float2(0, v_incr);
+ }
+ break;
+
+ case Ptex::e_top:
+ if (reverse) {
+ pos = make_float2(0, v_res);
+ incr = make_float2(u_incr, 0);
+ }
+ else {
+ pos = make_float2(u_res, v_res);
+ incr = make_float2(-u_incr, 0);
+ }
+ break;
+
+ case Ptex::e_left:
+ if (reverse) {
+ pos = make_float2(0, 0);
+ incr = make_float2(0, v_incr);
+ }
+ else {
+ pos = make_float2(0, v_res);
+ incr = make_float2(0, -v_incr);
+ }
+ }
+ }
+
+ void step() {
+ pos += incr;
+ }
+
+ void step(int n) {
+ pos += incr * n;
+ }
+
+ void copy_num_texels(PtexPackedTexture::Cursor &cursor,
+ const int num)
+ {
+ for (int i = 0; i < num; i++) {
+ copy_texel(cursor.data());
+ cursor.step();
+ step();
+ }
+ }
+
+ /* TODO(nicholasbishop): not doing any special filtering for
+ * adjacent faces of differing resolutions, not sure how much that
+ * will matter in practice */
+ void copy_texel(void *texel)
+ {
+ const int x = (int)(pos.x);
+ const int y = (int)(pos.y);
+ assert(x < face.res().u());
+ assert(y < face.res().v());
+ face.getPixel(x, y, texel);
+ }
+
+ PtexFaceData &face;
+ float2 pos;
+ float2 incr;
+};
+
+// TODO(nicholasbishop): this isn't necessarily the nicest or most
+// efficient way to go about this, easiest for now though since the
+// packing code is implemented on top of the Ptex API
+//
+// TODO(nicholasbishop): also now that I've written it looks gross.
+class BlenderPtexTexture : public PtexTexture {
+private:
+ class FaceData : public PtexFaceData {
+ public:
+ void *texels;
+ Ptex::Res cres;
+ int bytes_per_texel;
+
+ virtual void release()
+ {}
+
+ virtual bool isConstant()
+ {
+ return false;
+ }
+
+ virtual Ptex::Res res()
+ {
+ return cres;
+ }
+
+ virtual void getPixel(int u, int v, void *result)
+ {
+ if (texels) {
+ memcpy(result,
+ (char*)texels + (v * cres.u() + u) * bytes_per_texel,
+ bytes_per_texel);
+ }
+ }
+
+ virtual void *getData()
+ {
+ return texels;
+ }
+
+ virtual bool isTiled()
+ {
+ return false;
+ }
+
+ virtual Ptex::Res tileRes()
+ {
+ assert(!"tileRes not implemented");
+ }
+
+ virtual PtexFaceData *getTile(int tile)
+ {
+ assert(!"getTile not implemented");
+ }
+ };
+
+public:
+ BlenderPtexTexture(const LoopDataFunc loop_data,
+ void *loop_data_src,
+ const int num_loops,
+ const Ptex::DataType data_type,
+ const int num_channels,
+ const int alpha_channel)
+ : num_loops(num_loops),
+ data_type(data_type),
+ num_channels(num_channels),
+ alpha_channel(alpha_channel),
+ bytes_per_texel(num_channels * Ptex::DataSize(data_type))
+ {
+ face_info.reserve(num_loops);
+ face_data.reserve(num_loops);
+ for (int i = 0; i < num_loops; i++) {
+ FaceData fd;
+ int ulog2 = 0, vlog2 = 0;
+ loop_data(loop_data_src, i, &fd.texels, &ulog2, &vlog2);
+ Ptex::Res res(ulog2, vlog2);
+ fd.cres = res;
+ fd.bytes_per_texel = bytes_per_texel;
+
+ // Adjacency TODO
+ face_info.push_back(res);
+ face_data.push_back(fd);
+ }
+ }
+
+ virtual void release
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list