Commit: f9d25b0420f65da680045a1e4db3167666ba0f2f
Author: Nicholas Bishop
Date:   Fri Jan 16 12:27:41 2015 +0100
Branches: cycles-ptex-12
https://developer.blender.org/rBf9d25b0420f65da680045a1e4db3167666ba0f2f

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..d46f1e2
--- /dev/null
+++ b/extern/ptex/pack.cpp
@@ -0,0 +1,791 @@
+#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. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to