Merge branch 'master' into soc-2018-npr Fix errors
authorYiming Wu <xp8110@outlook.com>
Sat, 20 Apr 2019 06:10:24 +0000 (14:10 +0800)
committerYiming Wu <xp8110@outlook.com>
Sat, 20 Apr 2019 06:10:24 +0000 (14:10 +0800)
# Conflicts:
# intern/opensubdiv/internal/opensubdiv_evaluator.cc
# intern/opensubdiv/internal/opensubdiv_evaluator_internal.cc
# release/scripts/startup/bl_ui/properties_data_modifier.py
# source/blender/CMakeLists.txt
# source/blender/blenkernel/intern/scene.c
# source/blender/blenloader/intern/readfile.c
# source/blender/blenloader/intern/versioning_280.c
# source/blender/blenloader/intern/writefile.c
# source/blender/bmesh/intern/bmesh_polygon.c
# source/blender/draw/CMakeLists.txt
# source/blender/draw/intern/draw_manager.c
# source/blender/draw/modes/object_mode.c
# source/blender/editors/mesh/editmesh_tools.c
# source/blender/editors/mesh/mesh_ops.c
# source/blender/editors/render/render_intern.h
# source/blender/editors/render/render_ops.c
# source/blender/editors/space_outliner/outliner_draw.c
# source/blender/editors/space_view3d/space_view3d.c
# source/blender/makesdna/DNA_light_types.h
# source/blender/makesdna/DNA_modifier_types.h
# source/blender/makesdna/DNA_scene_types.h
# source/blender/makesdna/intern/makesdna.c
# source/blender/makesrna/intern/CMakeLists.txt
# source/blender/makesrna/intern/makesrna.c
# source/blender/makesrna/intern/rna_modifier.c
# source/blender/makesrna/intern/rna_scene.c
# source/blender/modifiers/CMakeLists.txt
# source/blender/modifiers/intern/MOD_util.c

65 files changed:
intern/opensubdiv/internal/opensubdiv_evaluator.cc
intern/opensubdiv/internal/opensubdiv_evaluator_internal.cc
intern/opensubdiv/internal/opensubdiv_evaluator_internal.h
intern/opensubdiv/opensubdiv_evaluator_capi.h
release/datafiles/locale
release/scripts/addons
release/scripts/addons_contrib
release/scripts/startup/bl_operators/__init__.py
release/scripts/startup/bl_operators/lanpr.py [new file with mode: 0644]
release/scripts/startup/bl_ui/properties_data_modifier.py
release/scripts/startup/bl_ui/properties_physics_fluid.py
release/scripts/startup/bl_ui/properties_scene.py
release/scripts/startup/bl_ui/space_view3d.py
source/blender/blenkernel/intern/scene.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/versioning_280.c
source/blender/blenloader/intern/writefile.c
source/blender/draw/CMakeLists.txt
source/blender/draw/engines/lanpr/lanpr_all.h [new file with mode: 0644]
source/blender/draw/engines/lanpr/lanpr_chain.c [new file with mode: 0644]
source/blender/draw/engines/lanpr/lanpr_dpix.c [new file with mode: 0644]
source/blender/draw/engines/lanpr/lanpr_engine.c [new file with mode: 0644]
source/blender/draw/engines/lanpr/lanpr_ops.c [new file with mode: 0644]
source/blender/draw/engines/lanpr/lanpr_snake.c [new file with mode: 0644]
source/blender/draw/engines/lanpr/lanpr_util.c [new file with mode: 0644]
source/blender/draw/engines/lanpr/lanpr_util.h [new file with mode: 0644]
source/blender/draw/engines/lanpr/shaders/lanpr_dpix_preview_frag.glsl [new file with mode: 0644]
source/blender/draw/engines/lanpr/shaders/lanpr_dpix_preview_geom.glsl [new file with mode: 0644]
source/blender/draw/engines/lanpr/shaders/lanpr_dpix_project_clip_frag.glsl [new file with mode: 0644]
source/blender/draw/engines/lanpr/shaders/lanpr_dpix_project_passthrough_vert.glsl [new file with mode: 0644]
source/blender/draw/engines/lanpr/shaders/lanpr_snake_edge_frag.glsl [new file with mode: 0644]
source/blender/draw/engines/lanpr/shaders/lanpr_snake_image_peel_frag.glsl [new file with mode: 0644]
source/blender/draw/engines/lanpr/shaders/lanpr_snake_line_connection_frag.glsl [new file with mode: 0644]
source/blender/draw/engines/lanpr/shaders/lanpr_snake_line_connection_geom.glsl [new file with mode: 0644]
source/blender/draw/engines/lanpr/shaders/lanpr_snake_line_connection_vert.glsl [new file with mode: 0644]
source/blender/draw/engines/lanpr/shaders/lanpr_snake_multichannel_frag.glsl [new file with mode: 0644]
source/blender/draw/engines/lanpr/shaders/lanpr_software_chain_geom.glsl [new file with mode: 0644]
source/blender/draw/engines/lanpr/shaders/lanpr_software_line_chain_geom.glsl [new file with mode: 0644]
source/blender/draw/engines/lanpr/shaders/lanpr_software_passthrough_vert.glsl [new file with mode: 0644]
source/blender/draw/intern/DRW_render.h
source/blender/draw/intern/draw_manager.c
source/blender/draw/intern/draw_manager_texture.c
source/blender/draw/modes/object_mode.c
source/blender/editors/mesh/editmesh_tools.c
source/blender/editors/mesh/mesh_intern.h
source/blender/editors/mesh/mesh_ops.c
source/blender/editors/render/render_intern.h
source/blender/editors/render/render_ops.c
source/blender/editors/space_view3d/space_view3d.c
source/blender/makesdna/DNA_lanpr_types.h [new file with mode: 0644]
source/blender/makesdna/DNA_modifier_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/intern/makesdna.c
source/blender/makesrna/RNA_access.h
source/blender/makesrna/intern/CMakeLists.txt
source/blender/makesrna/intern/makesrna.c
source/blender/makesrna/intern/rna_internal.h
source/blender/makesrna/intern/rna_lanpr.c [new file with mode: 0644]
source/blender/makesrna/intern/rna_modifier.c
source/blender/makesrna/intern/rna_scene.c
source/blender/modifiers/CMakeLists.txt
source/blender/modifiers/MOD_modifiertypes.h
source/blender/modifiers/intern/MOD_mybmesh.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_util.c
source/tools

index 2500691885c16d879d44547ab68c7602d54cea13..0fe9c7567eab2174ad608e24a31aecfd064fb67d 100644 (file)
 
 namespace {
 
-void setCoarsePositions(OpenSubdiv_Evaluator *evaluator,
-                        const float *positions,
-                        const int start_vertex_index,
-                        const int num_vertices)
-{
-  evaluator->internal->eval_output->setCoarsePositions(
-      positions, start_vertex_index, num_vertices);
+void setCoarsePositions(OpenSubdiv_Evaluator* evaluator,
+                        const float* positions,
+                        const int start_vertex_index, const int num_vertices) {
+  evaluator->internal->eval_output->setCoarsePositions(positions,
+                                                       start_vertex_index,
+                                                       num_vertices);
 }
 
-void setVaryingData(OpenSubdiv_Evaluator *evaluator,
-                    const float *varying_data,
-                    const int start_vertex_index,
-                    const int num_vertices)
-{
-  evaluator->internal->eval_output->setVaryingData(varying_data, start_vertex_index, num_vertices);
+void setVaryingData(OpenSubdiv_Evaluatorevaluator,
+                    const floatvarying_data,
+                    const int start_vertex_index, const int num_vertices) {
+  evaluator->internal->eval_output->setVaryingData(varying_data,
+                                                   start_vertex_index,
+                                                   num_vertices);
 }
 
-void setFaceVaryingData(OpenSubdiv_Evaluator *evaluator,
+void setFaceVaryingData(OpenSubdiv_Evaluatorevaluator,
                         const int face_varying_channel,
-                        const float *face_varying_data,
-                        const int start_vertex_index,
-                        const int num_vertices)
-{
-  evaluator->internal->eval_output->setFaceVaryingData(
-      face_varying_channel, face_varying_data, start_vertex_index, num_vertices);
+                        const floatface_varying_data,
+                        const int start_vertex_index, const int num_vertices) {
+  evaluator->internal->eval_output->setFaceVaryingData(face_varying_channel,
+                                                       face_varying_data,
+                                                       start_vertex_index,
+                                                       num_vertices);
 }
 
-void setCoarsePositionsFromBuffer(OpenSubdiv_Evaluator *evaluator,
-                                  const void *buffer,
+void setCoarsePositionsFromBuffer(OpenSubdiv_Evaluatorevaluator,
+                                  const voidbuffer,
                                   const int start_offset,
                                   const int stride,
                                   const int start_vertex_index,
-                                  const int num_vertices)
-{
+                                  const int num_vertices) {
   evaluator->internal->eval_output->setCoarsePositionsFromBuffer(
-      buffer, start_offset, stride, start_vertex_index, num_vertices);
+          buffer,
+          start_offset,
+          stride,
+          start_vertex_index,
+          num_vertices);
 }
 
-void setVaryingDataFromBuffer(OpenSubdiv_Evaluator *evaluator,
-                              const void *buffer,
+void setVaryingDataFromBuffer(OpenSubdiv_Evaluatorevaluator,
+                              const voidbuffer,
                               const int start_offset,
                               const int stride,
                               const int start_vertex_index,
-                              const int num_vertices)
-{
+                              const int num_vertices) {
   evaluator->internal->eval_output->setVaryingDataFromBuffer(
-      buffer, start_offset, stride, start_vertex_index, num_vertices);
+          buffer,
+          start_offset,
+          stride,
+          start_vertex_index,
+          num_vertices);
 }
 
-void setFaceVaryingDataFromBuffer(OpenSubdiv_Evaluator *evaluator,
+void setFaceVaryingDataFromBuffer(OpenSubdiv_Evaluatorevaluator,
                                   const int face_varying_channel,
-                                  const void *buffer,
+                                  const voidbuffer,
                                   const int start_offset,
                                   const int stride,
                                   const int start_vertex_index,
-                                  const int num_vertices)
-{
+                                  const int num_vertices) {
   evaluator->internal->eval_output->setFaceVaryingDataFromBuffer(
-      face_varying_channel, buffer, start_offset, stride, start_vertex_index, num_vertices);
+          face_varying_channel,
+          buffer,
+          start_offset,
+          stride,
+          start_vertex_index,
+          num_vertices);
 }
 
-void refine(OpenSubdiv_Evaluator *evaluator)
-{
+void refine(OpenSubdiv_Evaluator* evaluator) {
   evaluator->internal->eval_output->refine();
 }
 
-void evaluateLimit(OpenSubdiv_Evaluator *evaluator,
+void evaluateLimit(OpenSubdiv_Evaluatorevaluator,
                    const int ptex_face_index,
-                   const float face_u,
-                   const float face_v,
-                   float P[3],
-                   float dPdu[3],
-                   float dPdv[3])
-{
-  evaluator->internal->eval_output->evaluateLimit(ptex_face_index, face_u, face_v, P, dPdu, dPdv);
+                   const float face_u, const float face_v,
+                   float P[3], float dPdu[3], float dPdv[3]) {
+  evaluator->internal->eval_output->evaluateLimit(ptex_face_index,
+                                                  face_u, face_v,
+                                                  P, dPdu, dPdv);
 }
 
-void evaluateVarying(OpenSubdiv_Evaluator *evaluator,
+void evaluateLimit2(OpenSubdiv_Evaluator* evaluator,
+                   const int ptex_face_index,
+                   const float face_u, const float face_v,
+                                  float P[3],
+                                  float dPdu[3],
+                                  float dPdv[3],
+                                  float dPduu[3],
+                                  float dPduv[3],
+                                  float dPdvv[3]) {
+  evaluator->internal->eval_output->evaluateLimit2(ptex_face_index,
+                                                  face_u, face_v,
+                                                  P, dPdu, dPdv,
+                                                                                                 dPduu, dPduv, dPdvv);
+}
+
+void evaluateVarying(OpenSubdiv_Evaluator* evaluator,
                      const int ptex_face_index,
-                     float face_u,
-                     float face_v,
-                     float varying[3])
-{
-  evaluator->internal->eval_output->evaluateVarying(ptex_face_index, face_u, face_v, varying);
+                     float face_u, float face_v,
+                     float varying[3]) {
+  evaluator->internal->eval_output->evaluateVarying(ptex_face_index,
+                                                    face_u, face_v,
+                                                    varying);
 }
 
-void evaluateFaceVarying(OpenSubdiv_Evaluator *evaluator,
+void evaluateFaceVarying(OpenSubdiv_Evaluatorevaluator,
                          const int face_varying_channel,
                          const int ptex_face_index,
-                         float face_u,
-                         float face_v,
-                         float face_varying[2])
-{
+                         float face_u, float face_v,
+                         float face_varying[2]) {
   evaluator->internal->eval_output->evaluateFaceVarying(
       face_varying_channel, ptex_face_index, face_u, face_v, face_varying);
 }
 
-void assignFunctionPointers(OpenSubdiv_Evaluator *evaluator)
-{
+void assignFunctionPointers(OpenSubdiv_Evaluator* evaluator) {
   evaluator->setCoarsePositions = setCoarsePositions;
   evaluator->setVaryingData = setVaryingData;
   evaluator->setFaceVaryingData = setFaceVaryingData;
@@ -135,23 +153,22 @@ void assignFunctionPointers(OpenSubdiv_Evaluator *evaluator)
   evaluator->refine = refine;
 
   evaluator->evaluateLimit = evaluateLimit;
+  evaluator->evaluateLimit2 = evaluateLimit2;
   evaluator->evaluateVarying = evaluateVarying;
   evaluator->evaluateFaceVarying = evaluateFaceVarying;
 }
 
 }  // namespace
 
-OpenSubdiv_Evaluator *openSubdiv_createEvaluatorFromTopologyRefiner(
-    OpenSubdiv_TopologyRefiner *topology_refiner)
-{
-  OpenSubdiv_Evaluator *evaluator = OBJECT_GUARDED_NEW(OpenSubdiv_Evaluator);
+OpenSubdiv_Evaluator* openSubdiv_createEvaluatorFromTopologyRefiner(
+    OpenSubdiv_TopologyRefiner* topology_refiner) {
+  OpenSubdiv_Evaluator* evaluator = OBJECT_GUARDED_NEW(OpenSubdiv_Evaluator);
   assignFunctionPointers(evaluator);
   evaluator->internal = openSubdiv_createEvaluatorInternal(topology_refiner);
   return evaluator;
 }
 
-void openSubdiv_deleteEvaluator(OpenSubdiv_Evaluator *evaluator)
-{
+void openSubdiv_deleteEvaluator(OpenSubdiv_Evaluator* evaluator) {
   openSubdiv_deleteEvaluatorInternal(evaluator->internal);
   OBJECT_GUARDED_DELETE(evaluator, OpenSubdiv_Evaluator);
 }
index fa45c0119ec33a8c966b29fffc3b76c8ca5c6272..810ec4a8f91669e9dbf22512f2222d9fd5f2f12c 100644 (file)
 #include "internal/opensubdiv_util.h"
 #include "opensubdiv_topology_refiner_capi.h"
 
+using OpenSubdiv::Osd::BufferDescriptor;
+using OpenSubdiv::Osd::CpuEvaluator;
+using OpenSubdiv::Osd::CpuPatchTable;
+using OpenSubdiv::Osd::CpuVertexBuffer;
+using OpenSubdiv::Osd::PatchCoord;
 using OpenSubdiv::Far::PatchMap;
 using OpenSubdiv::Far::PatchTable;
 using OpenSubdiv::Far::PatchTableFactory;
 using OpenSubdiv::Far::StencilTable;
 using OpenSubdiv::Far::StencilTableFactory;
 using OpenSubdiv::Far::TopologyRefiner;
-using OpenSubdiv::Osd::BufferDescriptor;
-using OpenSubdiv::Osd::CpuEvaluator;
-using OpenSubdiv::Osd::CpuPatchTable;
-using OpenSubdiv::Osd::CpuVertexBuffer;
-using OpenSubdiv::Osd::PatchCoord;
 
 // TODO(sergey): Remove after official requirement bump for OSD version.
 #if OPENSUBDIV_VERSION_NUMBER >= 30200
@@ -70,27 +70,23 @@ namespace {
 // supported.
 class PatchCoordBuffer : public vector<PatchCoord> {
  public:
-  static PatchCoordBuffer *Create(int size)
-  {
-    PatchCoordBuffer *buffer = new PatchCoordBuffer();
+  static PatchCoordBuffer* Create(int size) {
+    PatchCoordBuffer* buffer = new PatchCoordBuffer();
     buffer->resize(size);
     return buffer;
   }
 
-  PatchCoord *BindCpuBuffer()
-  {
-    return reinterpret_cast<PatchCoord *>(&(*this)[0]);
+  PatchCoord* BindCpuBuffer() {
+    return reinterpret_cast<PatchCoord*>(&(*this)[0]);
   }
 
-  int GetNumVertices()
-  {
+  int GetNumVertices() {
     return size();
   }
 
-  void UpdateData(const PatchCoord *patch_coords, int num_patch_coords)
-  {
+  void UpdateData(const PatchCoord* patch_coords, int num_patch_coords) {
     memcpy(&(*this)[0],
-           reinterpret_cast<const void *>(patch_coords),
+           reinterpret_cast<const void*>(patch_coords),
            sizeof(PatchCoord) * num_patch_coords);
   }
 };
@@ -99,31 +95,26 @@ class PatchCoordBuffer : public vector<PatchCoord> {
 // coordinates to the CPU evaluator. Other evaluators are not supported.
 class SinglePatchCoordBuffer {
  public:
-  static SinglePatchCoordBuffer *Create()
-  {
+  static SinglePatchCoordBuffer* Create() {
     return new SinglePatchCoordBuffer();
   }
 
-  SinglePatchCoordBuffer()
-  {
+  SinglePatchCoordBuffer() {
   }
 
-  explicit SinglePatchCoordBuffer(const PatchCoord &patch_coord) : patch_coord_(patch_coord)
-  {
+  explicit SinglePatchCoordBuffer(const PatchCoord &patch_coord)
+      : patch_coord_(patch_coord) {
   }
 
-  PatchCoord *BindCpuBuffer()
-  {
+  PatchCoord* BindCpuBuffer() {
     return &patch_coord_;
   }
 
-  int GetNumVertices()
-  {
+  int GetNumVertices() {
     return 1;
   }
 
-  void UpdateData(const PatchCoord &patch_coord)
-  {
+  void UpdateData(const PatchCoord &patch_coord) {
     patch_coord_ = patch_coord;
   }
 
@@ -135,22 +126,20 @@ class SinglePatchCoordBuffer {
 // and better to be allocated in stack rather than in heap.
 //
 // TODO(sergey): Check if bare arrays could be used by CPU evaluator.
-template<int element_size, int num_vertices> class StackAllocatedBuffer {
+template <int element_size, int num_vertices>
+class StackAllocatedBuffer {
  public:
-  static PatchCoordBuffer *Create(int /*size*/)
-  {
+  static PatchCoordBuffer* Create(int /*size*/) {
     // TODO(sergey): Validate that requested size is smaller than static
     // stack memory size.
     return new StackAllocatedBuffer<element_size, num_vertices>();
   }
 
-  float *BindCpuBuffer()
-  {
+  float* BindCpuBuffer() {
     return &data_[0];
   }
 
-  int GetNumVertices()
-  {
+  int GetNumVertices() {
     return num_vertices;
   }
 
@@ -159,82 +148,87 @@ template<int element_size, int num_vertices> class StackAllocatedBuffer {
   float data_[element_size * num_vertices];
 };
 
-template<typename EVAL_VERTEX_BUFFER,
-         typename STENCIL_TABLE,
-         typename PATCH_TABLE,
-         typename EVALUATOR,
-         typename DEVICE_CONTEXT = void>
+template <typename EVAL_VERTEX_BUFFER,
+          typename STENCIL_TABLE,
+          typename PATCH_TABLE,
+          typename EVALUATOR,
+          typename DEVICE_CONTEXT = void>
 class FaceVaryingVolatileEval {
  public:
   typedef OpenSubdiv::Osd::EvaluatorCacheT<EVALUATOR> EvaluatorCache;
 
   FaceVaryingVolatileEval(int face_varying_channel,
-                          const StencilTable *face_varying_stencils,
+                          const StencilTableface_varying_stencils,
                           int face_varying_width,
-                          PATCH_TABLE *patch_table,
-                          EvaluatorCache *evaluator_cache = NULL,
-                          DEVICE_CONTEXT *device_context = NULL)
+                          PATCH_TABLEpatch_table,
+                          EvaluatorCacheevaluator_cache = NULL,
+                          DEVICE_CONTEXTdevice_context = NULL)
       : face_varying_channel_(face_varying_channel),
         src_face_varying_desc_(0, face_varying_width, face_varying_width),
         patch_table_(patch_table),
         evaluator_cache_(evaluator_cache),
-        device_context_(device_context)
-  {
+        device_context_(device_context) {
     using OpenSubdiv::Osd::convertToCompatibleStencilTable;
-    num_coarse_face_varying_vertices_ = face_varying_stencils->GetNumControlVertices();
-    const int num_total_face_varying_vertices = face_varying_stencils->GetNumControlVertices() +
-                                                face_varying_stencils->GetNumStencils();
-    src_face_varying_data_ = EVAL_VERTEX_BUFFER::Create(
-        2, num_total_face_varying_vertices, device_context);
-    face_varying_stencils_ = convertToCompatibleStencilTable<STENCIL_TABLE>(face_varying_stencils,
-                                                                            device_context_);
-  }
-
-  ~FaceVaryingVolatileEval()
-  {
+    num_coarse_face_varying_vertices_ =
+        face_varying_stencils->GetNumControlVertices();
+    const int num_total_face_varying_vertices =
+        face_varying_stencils->GetNumControlVertices() +
+        face_varying_stencils->GetNumStencils();
+    src_face_varying_data_ =
+        EVAL_VERTEX_BUFFER::Create(2,
+                                   num_total_face_varying_vertices,
+                                   device_context);
+    face_varying_stencils_ = convertToCompatibleStencilTable<STENCIL_TABLE>(
+        face_varying_stencils, device_context_);
+  }
+
+  ~FaceVaryingVolatileEval() {
     delete src_face_varying_data_;
     delete face_varying_stencils_;
   }
 
-  void updateData(const float *src, int start_vertex, int num_vertices)
-  {
-    src_face_varying_data_->UpdateData(src, start_vertex, num_vertices, device_context_);
+  void updateData(const float* src, int start_vertex, int num_vertices) {
+    src_face_varying_data_->UpdateData(src,
+                                       start_vertex,
+                                       num_vertices,
+                                       device_context_);
   }
 
-  void refine()
-  {
+  void refine() {
     BufferDescriptor dst_face_varying_desc = src_face_varying_desc_;
     dst_face_varying_desc.offset += num_coarse_face_varying_vertices_ *
                                     src_face_varying_desc_.stride;
-    const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
-        evaluator_cache_, src_face_varying_desc_, dst_face_varying_desc, device_context_);
-    EVALUATOR::EvalStencils(src_face_varying_data_,
-                            src_face_varying_desc_,
-                            src_face_varying_data_,
-                            dst_face_varying_desc,
+    const EVALUATOR* eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
+        evaluator_cache_,
+        src_face_varying_desc_,
+        dst_face_varying_desc,
+        device_context_);
+    EVALUATOR::EvalStencils(src_face_varying_data_, src_face_varying_desc_,
+                            src_face_varying_data_, dst_face_varying_desc,
                             face_varying_stencils_,
                             eval_instance,
                             device_context_);
   }
 
-  void evalPatch(const PatchCoord &patch_coord, float face_varying[2])
-  {
+  void evalPatch(const PatchCoord& patch_coord, float face_varying[2]) {
     StackAllocatedBuffer<2, 1> face_varying_data;
     BufferDescriptor face_varying_desc(0, 2, 2);
     SinglePatchCoordBuffer patch_coord_buffer(patch_coord);
-    const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
-        evaluator_cache_, src_face_varying_desc_, face_varying_desc, device_context_);
-    EVALUATOR::EvalPatchesFaceVarying(src_face_varying_data_,
-                                      src_face_varying_desc_,
-                                      &face_varying_data,
-                                      face_varying_desc,
-                                      patch_coord_buffer.GetNumVertices(),
-                                      &patch_coord_buffer,
-                                      patch_table_,
-                                      face_varying_channel_,
-                                      eval_instance,
-                                      device_context_);
-    const float *refined_face_varying = face_varying_data.BindCpuBuffer();
+    const EVALUATOR* eval_instance =
+        OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
+                                                 src_face_varying_desc_,
+                                                 face_varying_desc,
+                                                 device_context_);
+    EVALUATOR::EvalPatchesFaceVarying(
+        src_face_varying_data_, src_face_varying_desc_,
+        &face_varying_data, face_varying_desc,
+        patch_coord_buffer.GetNumVertices(),
+        &patch_coord_buffer,
+        patch_table_,
+        face_varying_channel_,
+        eval_instance,
+        device_context_);
+    const float* refined_face_varying = face_varying_data.BindCpuBuffer();
     memcpy(face_varying, refined_face_varying, sizeof(float) * 2);
   }
 
@@ -244,14 +238,14 @@ class FaceVaryingVolatileEval {
   BufferDescriptor src_face_varying_desc_;
 
   int num_coarse_face_varying_vertices_;
-  EVAL_VERTEX_BUFFER *src_face_varying_data_;
-  const STENCIL_TABLE *face_varying_stencils_;
+  EVAL_VERTEX_BUFFERsrc_face_varying_data_;
+  const STENCIL_TABLEface_varying_stencils_;
 
   // NOTE: We reference this, do not own it.
-  PATCH_TABLE *patch_table_;
+  PATCH_TABLEpatch_table_;
 
-  EvaluatorCache *evaluator_cache_;
-  DEVICE_CONTEXT *device_context_;
+  EvaluatorCacheevaluator_cache_;
+  DEVICE_CONTEXTdevice_context_;
 };
 
 // Volatile evaluator which can be used from threads.
@@ -260,12 +254,12 @@ class FaceVaryingVolatileEval {
 // TODO(sergey): Make it possible to evaluate multiple face varying layers.
 //               (or maybe, it's cheap to create new evaluator for existing
 //               topology to evaluate all needed face varying layers?)
-template<typename SRC_VERTEX_BUFFER,
-         typename EVAL_VERTEX_BUFFER,
-         typename STENCIL_TABLE,
-         typename PATCH_TABLE,
-         typename EVALUATOR,
-         typename DEVICE_CONTEXT = void>
+template <typename SRC_VERTEX_BUFFER,
+          typename EVAL_VERTEX_BUFFER,
+          typename STENCIL_TABLE,
+          typename PATCH_TABLE,
+          typename EVALUATOR,
+          typename DEVICE_CONTEXT = void>
 class VolatileEvalOutput {
  public:
   typedef OpenSubdiv::Osd::EvaluatorCacheT<EVALUATOR> EvaluatorCache;
@@ -273,141 +267,146 @@ class VolatileEvalOutput {
                                   STENCIL_TABLE,
                                   PATCH_TABLE,
                                   EVALUATOR,
-                                  DEVICE_CONTEXT>
-      FaceVaryingEval;
-
-  VolatileEvalOutput(const StencilTable *vertex_stencils,
-                     const StencilTable *varying_stencils,
-                     const vector<const StencilTable *> &all_face_varying_stencils,
-                     const int face_varying_width,
-                     const PatchTable *patch_table,
-                     EvaluatorCache *evaluator_cache = NULL,
-                     DEVICE_CONTEXT *device_context = NULL)
+                                  DEVICE_CONTEXT> FaceVaryingEval;
+
+  VolatileEvalOutput(
+      const StencilTable* vertex_stencils,
+      const StencilTable* varying_stencils,
+      const vector<const StencilTable*>& all_face_varying_stencils,
+      const int face_varying_width,
+      const PatchTable* patch_table,
+      EvaluatorCache* evaluator_cache = NULL,
+      DEVICE_CONTEXT* device_context = NULL)
       : src_desc_(0, 3, 3),
         src_varying_desc_(0, 3, 3),
         face_varying_width_(face_varying_width),
         evaluator_cache_(evaluator_cache),
-        device_context_(device_context)
-  {
+        device_context_(device_context) {
     // Total number of vertices = coarse points + refined points + local points.
     int num_total_vertices = vertex_stencils->GetNumControlVertices() +
                              vertex_stencils->GetNumStencils();
     num_coarse_vertices_ = vertex_stencils->GetNumControlVertices();
     using OpenSubdiv::Osd::convertToCompatibleStencilTable;
-    src_data_ = SRC_VERTEX_BUFFER::Create(3, num_total_vertices, device_context_);
-    src_varying_data_ = SRC_VERTEX_BUFFER::Create(3, num_total_vertices, device_context_);
+    src_data_ =
+        SRC_VERTEX_BUFFER::Create(3, num_total_vertices, device_context_);
+    src_varying_data_ =
+        SRC_VERTEX_BUFFER::Create(3, num_total_vertices, device_context_);
     patch_table_ = PATCH_TABLE::Create(patch_table, device_context_);
     patch_coords_ = NULL;
-    vertex_stencils_ = convertToCompatibleStencilTable<STENCIL_TABLE>(vertex_stencils,
-                                                                      device_context_);
-    varying_stencils_ = convertToCompatibleStencilTable<STENCIL_TABLE>(varying_stencils,
-                                                                       device_context_);
+    vertex_stencils_ = convertToCompatibleStencilTable<STENCIL_TABLE>(
+        vertex_stencils, device_context_);
+    varying_stencils_ = convertToCompatibleStencilTable<STENCIL_TABLE>(
+        varying_stencils, device_context_);
     // Create evaluators for every face varying channel.
     face_varying_evaluators.reserve(all_face_varying_stencils.size());
     int face_varying_channel = 0;
-    foreach (const StencilTable *face_varying_stencils, all_face_varying_stencils) {
-      face_varying_evaluators.push_back(new FaceVaryingEval(face_varying_channel,
-                                                            face_varying_stencils,
-                                                            face_varying_width,
-                                                            patch_table_,
-                                                            evaluator_cache_,
-                                                            device_context_));
+    foreach (const StencilTable* face_varying_stencils,
+             all_face_varying_stencils) {
+      face_varying_evaluators.push_back(
+          new FaceVaryingEval(face_varying_channel,
+                              face_varying_stencils,
+                              face_varying_width,
+                              patch_table_,
+                              evaluator_cache_,
+                              device_context_));
       ++face_varying_channel;
     }
   }
 
-  ~VolatileEvalOutput()
-  {
+  ~VolatileEvalOutput() {
     delete src_data_;
     delete src_varying_data_;
     delete patch_table_;
     delete vertex_stencils_;
     delete varying_stencils_;
-    foreach (FaceVaryingEval *face_varying_evaluator, face_varying_evaluators) {
+    foreach (FaceVaryingEvalface_varying_evaluator, face_varying_evaluators) {
       delete face_varying_evaluator;
     }
   }
 
   // TODO(sergey): Implement binding API.
 
-  void updateData(const float *src, int start_vertex, int num_vertices)
-  {
+  void updateData(const float* src, int start_vertex, int num_vertices) {
     src_data_->UpdateData(src, start_vertex, num_vertices, device_context_);
   }
 
-  void updateVaryingData(const float *src, int start_vertex, int num_vertices)
-  {
-    src_varying_data_->UpdateData(src, start_vertex, num_vertices, device_context_);
+  void updateVaryingData(const float* src, int start_vertex, int num_vertices) {
+    src_varying_data_->UpdateData(src,
+                                  start_vertex,
+                                  num_vertices,
+                                  device_context_);
   }
 
   void updateFaceVaryingData(const int face_varying_channel,
-                             const float *src,
+                             const floatsrc,
                              int start_vertex,
-                             int num_vertices)
-  {
+                             int num_vertices) {
     assert(face_varying_channel >= 0);
     assert(face_varying_channel < face_varying_evaluators.size());
-    face_varying_evaluators[face_varying_channel]->updateData(src, start_vertex, num_vertices);
+    face_varying_evaluators[face_varying_channel]->updateData(
+        src, start_vertex, num_vertices);
   }
 
-  bool hasVaryingData() const
-  {
+  bool hasVaryingData() const {
     // return varying_stencils_ != NULL;
     // TODO(sergey): Check this based on actual topology.
     return false;
   }
 
-  bool hasFaceVaryingData() const
-  {
+  bool hasFaceVaryingData() const {
     return face_varying_evaluators.size() != 0;
   }
 
-  void refine()
-  {
+  void refine() {
     // Evaluate vertex positions.
     BufferDescriptor dst_desc = src_desc_;
     dst_desc.offset += num_coarse_vertices_ * src_desc_.stride;
-    const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
-        evaluator_cache_, src_desc_, dst_desc, device_context_);
-    EVALUATOR::EvalStencils(src_data_,
-                            src_desc_,
-                            src_data_,
-                            dst_desc,
+    const EVALUATOR* eval_instance =
+        OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
+                                                 src_desc_,
+                                                 dst_desc,
+                                                 device_context_);
+    EVALUATOR::EvalStencils(src_data_, src_desc_,
+                            src_data_, dst_desc,
                             vertex_stencils_,
                             eval_instance,
                             device_context_);
     // Evaluate varying data.
     if (hasVaryingData()) {
       BufferDescriptor dst_varying_desc = src_varying_desc_;
-      dst_varying_desc.offset += num_coarse_vertices_ * src_varying_desc_.stride;
+      dst_varying_desc.offset +=
+          num_coarse_vertices_ * src_varying_desc_.stride;
       eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
-          evaluator_cache_, src_varying_desc_, dst_varying_desc, device_context_);
-      EVALUATOR::EvalStencils(src_varying_data_,
-                              src_varying_desc_,
-                              src_varying_data_,
-                              dst_varying_desc,
+          evaluator_cache_,
+          src_varying_desc_,
+          dst_varying_desc,
+          device_context_);
+      EVALUATOR::EvalStencils(src_varying_data_, src_varying_desc_,
+                              src_varying_data_, dst_varying_desc,
                               varying_stencils_,
-                              eval_instance,
-                              device_context_);
+                              eval_instance, device_context_);
     }
     // Evaluate face-varying data.
     if (hasFaceVaryingData()) {
-      foreach (FaceVaryingEval *face_varying_evaluator, face_varying_evaluators) {
+      foreach (FaceVaryingEval* face_varying_evaluator,
+               face_varying_evaluators) {
         face_varying_evaluator->refine();
       }
     }
   }
 
-  void evalPatchCoord(const PatchCoord &patch_coord, float P[3])
-  {
+  void evalPatchCoord(const PatchCoord& patch_coord, float P[3]) {
     StackAllocatedBuffer<6, 1> vertex_data;
     // TODO(sergey): Varying data is interleaved in vertex array, so need to
     // adjust stride if there is a varying data.
     // BufferDescriptor vertex_desc(0, 3, 6);
     BufferDescriptor vertex_desc(0, 3, 3);
     SinglePatchCoordBuffer patch_coord_buffer(patch_coord);
-    const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
-        evaluator_cache_, src_desc_, vertex_desc, device_context_);
+    const EVALUATOR* eval_instance =
+        OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
+                                                 src_desc_,
+                                                 vertex_desc,
+                                                 device_context_);
     EVALUATOR::EvalPatches(src_data_,
                            src_desc_,
                            &vertex_data,
@@ -417,15 +416,13 @@ class VolatileEvalOutput {
                            patch_table_,
                            eval_instance,
                            device_context_);
-    const float *refined_vertices = vertex_data.BindCpuBuffer();
+    const floatrefined_vertices = vertex_data.BindCpuBuffer();
     memcpy(P, refined_vertices, sizeof(float) * 3);
   }
 
-  void evalPatchesWithDerivatives(const PatchCoord &patch_coord,
+  void evalPatchesWithDerivatives(const PatchCoordpatch_coord,
                                   float P[3],
-                                  float dPdu[3],
-                                  float dPdv[3])
-  {
+                                  float dPdu[3], float dPdv[3]) {
     StackAllocatedBuffer<6, 1> vertex_data, derivatives;
     // TODO(sergey): Varying data is interleaved in vertex array, so need to
     // adjust stride if there is a varying data.
@@ -433,25 +430,25 @@ class VolatileEvalOutput {
     BufferDescriptor vertex_desc(0, 3, 3);
     BufferDescriptor du_desc(0, 3, 6), dv_desc(3, 3, 6);
     SinglePatchCoordBuffer patch_coord_buffer(patch_coord);
-    const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
-        evaluator_cache_, src_desc_, vertex_desc, du_desc, dv_desc, device_context_);
-    EVALUATOR::EvalPatches(src_data_,
-                           src_desc_,
-                           &vertex_data,
-                           vertex_desc,
-                           &derivatives,
-                           du_desc,
-                           &derivatives,
-                           dv_desc,
+    const EVALUATOR* eval_instance =
+        OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
+                                                 src_desc_,
+                                                 vertex_desc,
+                                                 du_desc, dv_desc,
+                                                 device_context_);
+    EVALUATOR::EvalPatches(src_data_, src_desc_,
+                           &vertex_data, vertex_desc,
+                           &derivatives, du_desc,
+                           &derivatives, dv_desc,
                            patch_coord_buffer.GetNumVertices(),
                            &patch_coord_buffer,
                            patch_table_,
                            eval_instance,
                            device_context_);
-    const float *refined_vertices = vertex_data.BindCpuBuffer();
+    const floatrefined_vertices = vertex_data.BindCpuBuffer();
     memcpy(P, refined_vertices, sizeof(float) * 3);
     if (dPdu != NULL || dPdv != NULL) {
-      const float *refined_derivatives = derivatives.BindCpuBuffer();
+      const floatrefined_derivatives = derivatives.BindCpuBuffer();
       if (dPdu != NULL) {
         memcpy(dPdu, refined_derivatives, sizeof(float) * 3);
       }
@@ -461,53 +458,116 @@ class VolatileEvalOutput {
     }
   }
 
-  void evalPatchVarying(const PatchCoord &patch_coord, float varying[3])
+  void evalPatchesWithDerivatives2(const PatchCoord& patch_coord,
+                 float P[3],
+                 float dPdu[3],
+                 float dPdv[3],
+                 float dPduu[3],
+                 float dPduv[3],
+                 float dPdvv[3])
   {
+         StackAllocatedBuffer<6, 1> vertex_data;
+         StackAllocatedBuffer<6, 1> derivatives;
+         StackAllocatedBuffer<6, 1> derivatives1;
+         StackAllocatedBuffer<6, 1> derivatives2;
+         BufferDescriptor vertex_desc(0, 3, 6),
+                                          du_desc(0, 3, 6),
+                                          dv_desc(3, 3, 6),
+                                          duu_desc(0, 3, 6),
+                                          duv_desc(3, 3, 6),
+                                          dvv_desc(0, 3, 6);
+         SinglePatchCoordBuffer patch_coord_buffer(patch_coord);
+         const EVALUATOR *eval_instance =
+                 OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
+                                 src_desc_,
+                                 vertex_desc,
+                                 du_desc,
+                                 dv_desc,
+                                 duu_desc,
+                                 duv_desc,
+                                 dvv_desc,
+                                 device_context_);
+         EVALUATOR::EvalPatches(src_data_, src_desc_,
+                         &vertex_data, vertex_desc,
+                         &derivatives, du_desc,
+                         &derivatives, dv_desc,
+                         &derivatives1, duu_desc,
+                         &derivatives1, duv_desc,
+                         &derivatives2, dvv_desc,
+                         patch_coord_buffer.GetNumVertices(),
+                         &patch_coord_buffer,
+                         patch_table_, eval_instance, device_context_);
+         float *refined_verts = vertex_data.BindCpuBuffer();
+         memcpy(P, refined_verts, sizeof(float) * 3);
+         if (dPdu != NULL || dPdv != NULL || dPduu != NULL || dPduv != NULL || dPdvv != NULL) {
+                 float *refined_drivatives = derivatives.BindCpuBuffer();
+                 float *refined_drivatives1 = derivatives1.BindCpuBuffer();
+                 float *refined_drivatives2 = derivatives2.BindCpuBuffer();
+                 if (dPdu) {
+                         memcpy(dPdu, refined_drivatives, sizeof(float) * 3);
+                 }
+                 if (dPdv) {
+                         memcpy(dPdv, refined_drivatives + 3, sizeof(float) * 3);
+                 }
+                 if (dPduu) {
+                         memcpy(dPduu, refined_drivatives1, sizeof(float) * 3);
+                 }
+                 if (dPduv) {
+                         memcpy(dPduv, refined_drivatives1 + 3, sizeof(float) * 3);
+                 }
+                 if (dPdvv) {
+                         memcpy(dPdvv, refined_drivatives2, sizeof(float) * 3);
+                 }
+         }
+  }
+
+  void evalPatchVarying(const PatchCoord& patch_coord, float varying[3]) {
     StackAllocatedBuffer<6, 1> varying_data;
     BufferDescriptor varying_desc(3, 3, 6);
     SinglePatchCoordBuffer patch_coord_buffer(patch_coord);
-    const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
-        evaluator_cache_, src_varying_desc_, varying_desc, device_context_);
-    EVALUATOR::EvalPatchesVarying(src_varying_data_,
-                                  src_varying_desc_,
-                                  &varying_data,
-                                  varying_desc,
+    const EVALUATOR* eval_instance =
+        OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(evaluator_cache_,
+                                                 src_varying_desc_,
+                                                 varying_desc,
+                                                 device_context_);
+    EVALUATOR::EvalPatchesVarying(src_varying_data_, src_varying_desc_,
+                                  &varying_data, varying_desc,
                                   patch_coord_buffer.GetNumVertices(),
                                   &patch_coord_buffer,
                                   patch_table_,
                                   eval_instance,
                                   device_context_);
-    const float *refined_varying = varying_data.BindCpuBuffer();
+    const floatrefined_varying = varying_data.BindCpuBuffer();
     memcpy(varying, refined_varying, sizeof(float) * 3);
   }
 
   void evalPatchFaceVarying(const int face_varying_channel,
-                            const PatchCoord &patch_coord,
-                            float face_varying[2])
-  {
+                            const PatchCoord& patch_coord,
+                            float face_varying[2]) {
     assert(face_varying_channel >= 0);
     assert(face_varying_channel < face_varying_evaluators.size());
-    face_varying_evaluators[face_varying_channel]->evalPatch(patch_coord, face_varying);
+    face_varying_evaluators[face_varying_channel]->evalPatch(
+        patch_coord, face_varying);
   }
 
  private:
-  SRC_VERTEX_BUFFER *src_data_;
-  SRC_VERTEX_BUFFER *src_varying_data_;
-  PatchCoordBuffer *patch_coords_;
-  PATCH_TABLE *patch_table_;
+  SRC_VERTEX_BUFFERsrc_data_;
+  SRC_VERTEX_BUFFERsrc_varying_data_;
+  PatchCoordBufferpatch_coords_;
+  PATCH_TABLEpatch_table_;
   BufferDescriptor src_desc_;
   BufferDescriptor src_varying_desc_;
 
   int num_coarse_vertices_;
 
-  const STENCIL_TABLE *vertex_stencils_;
-  const STENCIL_TABLE *varying_stencils_;
+  const STENCIL_TABLEvertex_stencils_;
+  const STENCIL_TABLEvarying_stencils_;
 
   int face_varying_width_;
-  vector<FaceVaryingEval *> face_varying_evaluators;
+  vector<FaceVaryingEval*> face_varying_evaluators;
 
-  EvaluatorCache *evaluator_cache_;
-  DEVICE_CONTEXT *device_context_;
+  EvaluatorCacheevaluator_cache_;
+  DEVICE_CONTEXTdevice_context_;
 };
 
 }  // namespace
@@ -520,12 +580,12 @@ class CpuEvalOutput : public VolatileEvalOutput<CpuVertexBuffer,
                                                 CpuPatchTable,
                                                 CpuEvaluator> {
  public:
-  CpuEvalOutput(const StencilTable *vertex_stencils,
-                const StencilTable *varying_stencils,
-                const vector<const StencilTable *> &all_face_varying_stencils,
+  CpuEvalOutput(const StencilTablevertex_stencils,
+                const StencilTablevarying_stencils,
+                const vector<const StencilTable*>& all_face_varying_stencils,
                 const int face_varying_width,
-                const PatchTable *patch_table,
-                EvaluatorCache *evaluator_cache = NULL)
+                const PatchTablepatch_table,
+                EvaluatorCacheevaluator_cache = NULL)
       : VolatileEvalOutput<CpuVertexBuffer,
                            CpuVertexBuffer,
                            StencilTable,
@@ -535,179 +595,198 @@ class CpuEvalOutput : public VolatileEvalOutput<CpuVertexBuffer,
                                          all_face_varying_stencils,
                                          face_varying_width,
                                          patch_table,
-                                         evaluator_cache)
-  {
+                                         evaluator_cache) {
   }
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 // Evaluator wrapper for anonymous API.
 
-CpuEvalOutputAPI::CpuEvalOutputAPI(CpuEvalOutput *implementation,
-                                   OpenSubdiv::Far::PatchMap *patch_map)
-    : implementation_(implementation), patch_map_(patch_map)
-{
+CpuEvalOutputAPI::CpuEvalOutputAPI(CpuEvalOutputimplementation,
+                                   OpenSubdiv::Far::PatchMappatch_map)
+    : implementation_(implementation),
+      patch_map_(patch_map) {
 }
 
-CpuEvalOutputAPI::~CpuEvalOutputAPI()
-{
+CpuEvalOutputAPI::~CpuEvalOutputAPI() {
   delete implementation_;
 }
 
-void CpuEvalOutputAPI::setCoarsePositions(const float *positions,
+void CpuEvalOutputAPI::setCoarsePositions(const floatpositions,
                                           const int start_vertex_index,
-                                          const int num_vertices)
-{
+                                          const int num_vertices) {
   // TODO(sergey): Add sanity check on indices.
   implementation_->updateData(positions, start_vertex_index, num_vertices);
 }
 
-void CpuEvalOutputAPI::setVaryingData(const float *varying_data,
+void CpuEvalOutputAPI::setVaryingData(const floatvarying_data,
                                       const int start_vertex_index,
-                                      const int num_vertices)
-{
+                                      const int num_vertices) {
   // TODO(sergey): Add sanity check on indices.
-  implementation_->updateVaryingData(varying_data, start_vertex_index, num_vertices);
+  implementation_->updateVaryingData(varying_data,
+                                     start_vertex_index,
+                                     num_vertices);
 }
 
 void CpuEvalOutputAPI::setFaceVaryingData(const int face_varying_channel,
-                                          const float *face_varying_data,
+                                          const floatface_varying_data,
                                           const int start_vertex_index,
-                                          const int num_vertices)
-{
+                                          const int num_vertices) {
   // TODO(sergey): Add sanity check on indices.
-  implementation_->updateFaceVaryingData(
-      face_varying_channel, face_varying_data, start_vertex_index, num_vertices);
+  implementation_->updateFaceVaryingData(face_varying_channel,
+                                         face_varying_data,
+                                         start_vertex_index,
+                                         num_vertices);
 }
 
-void CpuEvalOutputAPI::setCoarsePositionsFromBuffer(const void *buffer,
-                                                    const int start_offset,
-                                                    const int stride,
-                                                    const int start_vertex_index,
-                                                    const int num_vertices)
-{
+void CpuEvalOutputAPI::setCoarsePositionsFromBuffer(
+    const void* buffer,
+    const int start_offset,
+    const int stride,
+    const int start_vertex_index,
+    const int num_vertices) {
   // TODO(sergey): Add sanity check on indices.
-  const unsigned char *current_buffer = (unsigned char *)buffer;
+  const unsigned charcurrent_buffer = (unsigned char *)buffer;
   current_buffer += start_offset;
   for (int i = 0; i < num_vertices; ++i) {
     const int current_vertex_index = start_vertex_index + i;
-    implementation_->updateData(
-        reinterpret_cast<const float *>(current_buffer), current_vertex_index, 1);
+    implementation_->updateData(reinterpret_cast<const float*>(current_buffer),
+                                current_vertex_index, 1);
     current_buffer += stride;
   }
 }
 
-void CpuEvalOutputAPI::setVaryingDataFromBuffer(const void *buffer,
-                                                const int start_offset,
-                                                const int stride,
-                                                const int start_vertex_index,
-                                                const int num_vertices)
-{
+void CpuEvalOutputAPI::setVaryingDataFromBuffer(
+    const void* buffer,
+    const int start_offset,
+    const int stride,
+    const int start_vertex_index,
+    const int num_vertices) {
   // TODO(sergey): Add sanity check on indices.
-  const unsigned char *current_buffer = (unsigned char *)buffer;
+  const unsigned charcurrent_buffer = (unsigned char *)buffer;
   current_buffer += start_offset;
   for (int i = 0; i < num_vertices; ++i) {
     const int current_vertex_index = start_vertex_index + i;
     implementation_->updateVaryingData(
-        reinterpret_cast<const float *>(current_buffer), current_vertex_index, 1);
+        reinterpret_cast<const float*>(current_buffer),
+        current_vertex_index, 1);
     current_buffer += stride;
   }
 }
 
-void CpuEvalOutputAPI::setFaceVaryingDataFromBuffer(const int face_varying_channel,
-                                                    const void *buffer,
-                                                    const int start_offset,
-                                                    const int stride,
-                                                    const int start_vertex_index,
-                                                    const int num_vertices)
-{
+void CpuEvalOutputAPI::setFaceVaryingDataFromBuffer(
+    const int face_varying_channel,
+    const void* buffer,
+    const int start_offset,
+    const int stride,
+    const int start_vertex_index,
+    const int num_vertices) {
   // TODO(sergey): Add sanity check on indices.
-  const unsigned char *current_buffer = (unsigned char *)buffer;
+  const unsigned charcurrent_buffer = (unsigned char *)buffer;
   current_buffer += start_offset;
   for (int i = 0; i < num_vertices; ++i) {
     const int current_vertex_index = start_vertex_index + i;
-    implementation_->updateFaceVaryingData(face_varying_channel,
-                                           reinterpret_cast<const float *>(current_buffer),
-                                           current_vertex_index,
-                                           1);
+    implementation_->updateFaceVaryingData(
+        face_varying_channel,
+        reinterpret_cast<const float*>(current_buffer),
+        current_vertex_index, 1);
     current_buffer += stride;
   }
 }
 
-void CpuEvalOutputAPI::refine()
-{
+void CpuEvalOutputAPI::refine() {
   implementation_->refine();
 }
 
 void CpuEvalOutputAPI::evaluateLimit(const int ptex_face_index,
-                                     float face_u,
-                                     float face_v,
-                                     float P[3],
-                                     float dPdu[3],
-                                     float dPdv[3])
-{
+                                     float face_u, float face_v,
+                                     float P[3], float dPdu[3], float dPdv[3]) {
   assert(face_u >= 0.0f);
   assert(face_u <= 1.0f);
   assert(face_v >= 0.0f);
   assert(face_v <= 1.0f);
-  const PatchTable::PatchHandle *handle = patch_map_->FindPatch(ptex_face_index, face_u, face_v);
+  const PatchTable::PatchHandle* handle =
+      patch_map_->FindPatch(ptex_face_index, face_u, face_v);
   PatchCoord patch_coord(*handle, face_u, face_v);
   if (dPdu != NULL || dPdv != NULL) {
     implementation_->evalPatchesWithDerivatives(patch_coord, P, dPdu, dPdv);
-  }
-  else {
+  } else {
     implementation_->evalPatchCoord(patch_coord, P);
-  }
-}
+  }}
+
+void CpuEvalOutputAPI::evaluateLimit2(const int ptex_face_index,
+                                                                         float face_u, float face_v,
+                                                                         float P[3],
+                                                                         float dPdu[3],
+                                                                         float dPdv[3],
+                                                                         float dPduu[3],
+                                                                         float dPduv[3],
+                                                                         float dPdvv[3]) {
+  assert(face_u >= 0.0f);
+  assert(face_u <= 1.0f);
+  assert(face_v >= 0.0f);
+  assert(face_v <= 1.0f);
+  const PatchTable::PatchHandle* handle =
+      patch_map_->FindPatch(ptex_face_index, face_u, face_v);
+  PatchCoord patch_coord(*handle, face_u, face_v);
+  if (dPdu != NULL || dPdv != NULL || dPduu != NULL || dPduv != NULL || dPdvv != NULL ) {
+       implementation_->evalPatchesWithDerivatives2(patch_coord,
+                         P,
+                         dPdu,
+                         dPdv,
+                         dPduu,
+                         dPduv,
+                         dPdvv);
+  } else {
+    implementation_->evalPatchCoord(patch_coord, P);
+  }}
 
 void CpuEvalOutputAPI::evaluateVarying(const int ptex_face_index,
-                                       float face_u,
-                                       float face_v,
-                                       float varying[3])
-{
+                                       float face_u, float face_v,
+                                       float varying[3]) {
   assert(face_u >= 0.0f);
   assert(face_u <= 1.0f);
   assert(face_v >= 0.0f);
   assert(face_v <= 1.0f);
-  const PatchTable::PatchHandle *handle = patch_map_->FindPatch(ptex_face_index, face_u, face_v);
+  const PatchTable::PatchHandle* handle =
+      patch_map_->FindPatch(ptex_face_index, face_u, face_v);
   PatchCoord patch_coord(*handle, face_u, face_v);
   implementation_->evalPatchVarying(patch_coord, varying);
 }
 
 void CpuEvalOutputAPI::evaluateFaceVarying(const int face_varying_channel,
                                            const int ptex_face_index,
-                                           float face_u,
-                                           float face_v,
-                                           float face_varying[2])
-{
+                                           float face_u, float face_v,
+                                           float face_varying[2]) {
   assert(face_u >= 0.0f);
   assert(face_u <= 1.0f);
   assert(face_v >= 0.0f);
   assert(face_v <= 1.0f);
-  const PatchTable::PatchHandle *handle = patch_map_->FindPatch(ptex_face_index, face_u, face_v);
+  const PatchTable::PatchHandle* handle =
+      patch_map_->FindPatch(ptex_face_index, face_u, face_v);
   PatchCoord patch_coord(*handle, face_u, face_v);
-  implementation_->evalPatchFaceVarying(face_varying_channel, patch_coord, face_varying);
+  implementation_->evalPatchFaceVarying(
+      face_varying_channel, patch_coord, face_varying);
 }
 
 }  // namespace opensubdiv_capi
 
 OpenSubdiv_EvaluatorInternal::OpenSubdiv_EvaluatorInternal()
-    : eval_output(NULL), patch_map(NULL), patch_table(NULL)
-{
+    : eval_output(NULL),
+      patch_map(NULL),
+      patch_table(NULL) {
 }
 
-OpenSubdiv_EvaluatorInternal::~OpenSubdiv_EvaluatorInternal()
-{
+OpenSubdiv_EvaluatorInternal::~OpenSubdiv_EvaluatorInternal() {
   delete eval_output;
   delete patch_map;
   delete patch_table;
 }
 
-OpenSubdiv_EvaluatorInternal *openSubdiv_createEvaluatorInternal(
-    OpenSubdiv_TopologyRefiner *topology_refiner)
-{
+OpenSubdiv_EvaluatorInternal* openSubdiv_createEvaluatorInternal(
+    OpenSubdiv_TopologyRefiner* topology_refiner) {
   using opensubdiv_capi::vector;
-  TopologyRefiner *refiner = topology_refiner->internal->osd_topology_refiner;
+  TopologyRefinerrefiner = topology_refiner->internal->osd_topology_refiner;
   if (refiner == NULL) {
     // Happens on bad topology.
     return NULL;
@@ -729,8 +808,7 @@ OpenSubdiv_EvaluatorInternal *openSubdiv_createEvaluatorInternal(
     options.considerFVarChannels = has_face_varying_data;
     options.useInfSharpPatch = use_inf_sharp_patch;
     refiner->RefineAdaptive(options);
-  }
-  else {
+  } else {
     TopologyRefiner::UniformOptions options(level);
     refiner->RefineUniform(options);
   }
@@ -740,31 +818,38 @@ OpenSubdiv_EvaluatorInternal *openSubdiv_createEvaluatorInternal(
   // Vertex stencils.
   StencilTableFactory::Options vertex_stencil_options;
   vertex_stencil_options.generateOffsets = stencil_generate_offsets;
-  vertex_stencil_options.generateIntermediateLevels = stencil_generate_intermediate_levels;
-  const StencilTable *vertex_stencils = StencilTableFactory::Create(*refiner,
-                                                                    vertex_stencil_options);
+  vertex_stencil_options.generateIntermediateLevels =
+      stencil_generate_intermediate_levels;
+  const StencilTable* vertex_stencils =
+      StencilTableFactory::Create(*refiner, vertex_stencil_options);
   // Varying stencils.
   //
   // TODO(sergey): Seems currently varying stencils are always required in
   // OpenSubdiv itself.
-  const StencilTable *varying_stencils = NULL;
+  const StencilTablevarying_stencils = NULL;
   if (has_varying_data) {
     StencilTableFactory::Options varying_stencil_options;
     varying_stencil_options.generateOffsets = stencil_generate_offsets;
-    varying_stencil_options.generateIntermediateLevels = stencil_generate_intermediate_levels;
-    varying_stencil_options.interpolationMode = StencilTableFactory::INTERPOLATE_VARYING;
-    varying_stencils = StencilTableFactory::Create(*refiner, varying_stencil_options);
+    varying_stencil_options.generateIntermediateLevels =
+        stencil_generate_intermediate_levels;
+    varying_stencil_options.interpolationMode =
+        StencilTableFactory::INTERPOLATE_VARYING;
+    varying_stencils =
+        StencilTableFactory::Create(*refiner, varying_stencil_options);
   }
   // Face warying stencil.
-  vector<const StencilTable *> all_face_varying_stencils;
+vector<const StencilTable*> all_face_varying_stencils;
 #ifdef OPENSUBDIV_HAS_FVAR_EVALUATION
   all_face_varying_stencils.reserve(num_face_varying_channels);
-  for (int face_varying_channel = 0; face_varying_channel < num_face_varying_channels;
+  for (int face_varying_channel = 0;
+       face_varying_channel < num_face_varying_channels;
        ++face_varying_channel) {
     StencilTableFactory::Options face_varying_stencil_options;
     face_varying_stencil_options.generateOffsets = stencil_generate_offsets;
-    face_varying_stencil_options.generateIntermediateLevels = stencil_generate_intermediate_levels;
-    face_varying_stencil_options.interpolationMode = StencilTableFactory::INTERPOLATE_FACE_VARYING;
+    face_varying_stencil_options.generateIntermediateLevels =
+        stencil_generate_intermediate_levels;
+    face_varying_stencil_options.interpolationMode =
+        StencilTableFactory::INTERPOLATE_FACE_VARYING;
     face_varying_stencil_options.fvarChannel = face_varying_channel;
     all_face_varying_stencils.push_back(
         StencilTableFactory::Create(*refiner, face_varying_stencil_options));
@@ -779,35 +864,42 @@ OpenSubdiv_EvaluatorInternal *openSubdiv_createEvaluatorInternal(
   patch_options.useInfSharpPatch = use_inf_sharp_patch;
   patch_options.generateFVarTables = has_face_varying_data;
   patch_options.generateFVarLegacyLinearPatches = false;
-  const PatchTable *patch_table = PatchTableFactory::Create(*refiner, patch_options);
+  const PatchTable* patch_table = PatchTableFactory::Create(
+      *refiner, patch_options);
   // Append local points stencils.
   // Point stencils.
-  const StencilTable *local_point_stencil_table = patch_table->GetLocalPointStencilTable();
+  const StencilTable* local_point_stencil_table =
+      patch_table->GetLocalPointStencilTable();
   if (local_point_stencil_table != NULL) {
-    const StencilTable *table = StencilTableFactory::AppendLocalPointStencilTable(
-        *refiner, vertex_stencils, local_point_stencil_table);
+    const StencilTable* table =
+        StencilTableFactory::AppendLocalPointStencilTable(
+            *refiner, vertex_stencils, local_point_stencil_table);
     delete vertex_stencils;
     vertex_stencils = table;
   }
   // Varying stencils.
   if (has_varying_data) {
-    const StencilTable *local_point_varying_stencil_table =
+    const StencilTablelocal_point_varying_stencil_table =
         patch_table->GetLocalPointVaryingStencilTable();
     if (local_point_varying_stencil_table != NULL) {
-      const StencilTable *table = StencilTableFactory::AppendLocalPointStencilTable(
-          *refiner, varying_stencils, local_point_varying_stencil_table);
+      const StencilTable* table =
+          StencilTableFactory::AppendLocalPointStencilTable(
+              *refiner, varying_stencils, local_point_varying_stencil_table);
       delete varying_stencils;
       varying_stencils = table;
     }
   }
 #ifdef OPENSUBDIV_HAS_FVAR_EVALUATION
-  for (int face_varying_channel = 0; face_varying_channel < num_face_varying_channels;
+  for (int face_varying_channel = 0;
+       face_varying_channel < num_face_varying_channels;
        ++face_varying_channel) {
-    const StencilTable *table = StencilTableFactory::AppendLocalPointStencilTableFaceVarying(
-        *refiner,
-        all_face_varying_stencils[face_varying_channel],
-        patch_table->GetLocalPointFaceVaryingStencilTable(face_varying_channel),
-        face_varying_channel);
+    const StencilTable* table =
+        StencilTableFactory::AppendLocalPointStencilTableFaceVarying(
+              *refiner,
+              all_face_varying_stencils[face_varying_channel],
+              patch_table->GetLocalPointFaceVaryingStencilTable(
+                  face_varying_channel),
+              face_varying_channel);
     if (table != NULL) {
       delete all_face_varying_stencils[face_varying_channel];
       all_face_varying_stencils[face_varying_channel] = table;
@@ -816,25 +908,30 @@ OpenSubdiv_EvaluatorInternal *openSubdiv_createEvaluatorInternal(
 #endif
   // Create OpenSubdiv's CPU side evaluator.
   // TODO(sergey): Make it possible to use different evaluators.
-  opensubdiv_capi::CpuEvalOutput *eval_output = new opensubdiv_capi::CpuEvalOutput(
-      vertex_stencils, varying_stencils, all_face_varying_stencils, 2, patch_table);
-  OpenSubdiv::Far::PatchMap *patch_map = new PatchMap(*patch_table);
+  opensubdiv_capi::CpuEvalOutput* eval_output =
+      new opensubdiv_capi::CpuEvalOutput(vertex_stencils,
+                                         varying_stencils,
+                                         all_face_varying_stencils,
+                                         2,
+                                         patch_table);
+  OpenSubdiv::Far::PatchMap* patch_map = new PatchMap(*patch_table);
   // Wrap everything we need into an object which we control from our side.
-  OpenSubdiv_EvaluatorInternal *evaluator_descr;
+  OpenSubdiv_EvaluatorInternalevaluator_descr;
   evaluator_descr = OBJECT_GUARDED_NEW(OpenSubdiv_EvaluatorInternal);
-  evaluator_descr->eval_output = new opensubdiv_capi::CpuEvalOutputAPI(eval_output, patch_map);
+  evaluator_descr->eval_output =
+      new opensubdiv_capi::CpuEvalOutputAPI(eval_output, patch_map);
   evaluator_descr->patch_map = patch_map;
   evaluator_descr->patch_table = patch_table;
   // TOOD(sergey): Look into whether we've got duplicated stencils arrays.
   delete vertex_stencils;
   delete varying_stencils;
-  foreach (const StencilTable *table, all_face_varying_stencils) {
+  foreach (const StencilTabletable, all_face_varying_stencils) {
     delete table;
   }
   return evaluator_descr;
 }
 
-void openSubdiv_deleteEvaluatorInternal(OpenSubdiv_EvaluatorInternal *evaluator)
-{
+void openSubdiv_deleteEvaluatorInternal(
+    OpenSubdiv_EvaluatorInternal* evaluator) {
   OBJECT_GUARDED_DELETE(evaluator, OpenSubdiv_EvaluatorInternal);
 }
index 7c963227d17d4fe84b05b134edc7de4351ec386e..4e5d396b57b42b529dd7ad0240fca0cb363c4dc5 100644 (file)
@@ -42,30 +42,29 @@ class CpuEvalOutput;
 class CpuEvalOutputAPI {
  public:
   // NOTE: API object becomes an owner of evaluator. Patch we are referencing.
-  CpuEvalOutputAPI(CpuEvalOutput *implementation, OpenSubdiv::Far::PatchMap *patch_map);
+  CpuEvalOutputAPI(CpuEvalOutput* implementation,
+                   OpenSubdiv::Far::PatchMap* patch_map);
   ~CpuEvalOutputAPI();
 
   // Set coarse positions from a continuous array of coordinates.
-  void setCoarsePositions(const float *positions,
+  void setCoarsePositions(const floatpositions,
                           const int start_vertex_index,
                           const int num_vertices);
   // Set varying data from a continuous array of data.
-  void setVaryingData(const float *varying_data,
-                      const int start_vertex_index,
-                      const int num_vertices);
+  void setVaryingData(const float* varying_data,
+                      const int start_vertex_index, const int num_vertices);
   // Set face varying data from a continuous array of data.
   //
   // TODO(sergey): Find a better name for vertex here. It is not the vertex of
   // geometry, but a vertex of UV map.
   void setFaceVaryingData(const int face_varying_channel,
-                          const float *varying_data,
-                          const int start_vertex_index,
-                          const int num_vertices);
+                          const float* varying_data,
+                          const int start_vertex_index, const int num_vertices);
 
   // Set coarse vertex position from a continuous memory buffer where
   // first coordinate starts at offset of `start_offset` and there is `stride`
   // bytes between adjacent vertex coordinates.
-  void setCoarsePositionsFromBuffer(const void *buffer,
+  void setCoarsePositionsFromBuffer(const voidbuffer,
                                     const int start_offset,
                                     const int stride,
                                     const int start_vertex_index,
@@ -73,7 +72,7 @@ class CpuEvalOutputAPI {
   // Set varying data from a continuous memory buffer where
   // first coordinate starts at offset of `start_offset` and there is `stride`
   // bytes between adjacent vertex coordinates.
-  void setVaryingDataFromBuffer(const void *buffer,
+  void setVaryingDataFromBuffer(const voidbuffer,
                                 const int start_offset,
                                 const int stride,
                                 const int start_vertex_index,
@@ -85,7 +84,7 @@ class CpuEvalOutputAPI {
   // TODO(sergey): Find a better name for vertex here. It is not the vertex of
   // geometry, but a vertex of UV map.
   void setFaceVaryingDataFromBuffer(const int face_varying_channel,
-                                    const void *buffer,
+                                    const voidbuffer,
                                     const int start_offset,
                                     const int stride,
                                     const int start_vertex_index,
@@ -97,26 +96,33 @@ class CpuEvalOutputAPI {
   // Evaluate given ptex face at given bilinear coordinate.
   // If derivatives are NULL, they will not be evaluated.
   void evaluateLimit(const int ptex_face_index,
-                     float face_u,
-                     float face_v,
-                     float P[3],
-                     float dPdu[3],
-                     float dPdv[3]);
+                     float face_u, float face_v,
+                     float P[3], float dPdu[3], float dPdv[3]);
+
+  void evaluateLimit2(const int ptex_face_index,
+                                         float face_u, float face_v,
+                                         float P[3],
+                                         float dPdu[3],
+                                         float dPdv[3],
+                                         float dPduu[3],
+                                         float dPduv[3],
+                                         float dPdvv[3]);
 
   // Evaluate varying data at a given bilinear coordinate of given ptex face.
-  void evaluateVarying(const int ptes_face_index, float face_u, float face_v, float varying[3]);
+  void evaluateVarying(const int ptes_face_index,
+                       float face_u, float face_v,
+                       float varying[3]);
 
   // Evaluate facee-varying data at a given bilinear coordinate of given
   // ptex face.
   void evaluateFaceVarying(const int face_varying_channel,
                            const int ptes_face_index,
-                           float face_u,
-                           float face_v,
+                           float face_u, float face_v,
                            float face_varying[2]);
 
  protected:
-  CpuEvalOutput *implementation_;
-  OpenSubdiv::Far::PatchMap *patch_map_;
+  CpuEvalOutputimplementation_;
+  OpenSubdiv::Far::PatchMappatch_map_;
 };
 
 }  // namespace opensubdiv_capi
@@ -126,14 +132,15 @@ struct OpenSubdiv_EvaluatorInternal {
   OpenSubdiv_EvaluatorInternal();
   ~OpenSubdiv_EvaluatorInternal();
 
-  opensubdiv_capi::CpuEvalOutputAPI *eval_output;
-  const OpenSubdiv::Far::PatchMap *patch_map;
-  const OpenSubdiv::Far::PatchTable *patch_table;
+  opensubdiv_capi::CpuEvalOutputAPIeval_output;
+  const OpenSubdiv::Far::PatchMappatch_map;
+  const OpenSubdiv::Far::PatchTablepatch_table;
 };
 
-OpenSubdiv_EvaluatorInternal *openSubdiv_createEvaluatorInternal(
-    struct OpenSubdiv_TopologyRefiner *topology_refiner);
+OpenSubdiv_EvaluatorInternalopenSubdiv_createEvaluatorInternal(
+    struct OpenSubdiv_TopologyRefinertopology_refiner);
 
-void openSubdiv_deleteEvaluatorInternal(OpenSubdiv_EvaluatorInternal *evaluator);
+void openSubdiv_deleteEvaluatorInternal(
+    OpenSubdiv_EvaluatorInternal* evaluator);
 
 #endif  // OPENSUBDIV_EVALUATOR_INTERNAL_H_
index ceb0c58feba689efd5ddd9c8e6cb10f3feba1976..a84a52b13f358ed548e1d0821939ca800f5dd697 100644 (file)
@@ -92,6 +92,16 @@ typedef struct OpenSubdiv_Evaluator {
                         float dPdu[3],
                         float dPdv[3]);
 
+  void (*evaluateLimit2)(struct OpenSubdiv_Evaluator* evaluator,
+                        const int ptex_face_index,
+                        float face_u, float face_v,
+                                               float P[3],
+                                               float dPdu[3],
+                                               float dPdv[3],
+                                               float dPduu[3],
+                                               float dPduv[3],
+                                               float dPdvv[3]);
+
   // Evaluate varying data at a given bilinear coordinate of given ptex face.
   void (*evaluateVarying)(struct OpenSubdiv_Evaluator *evaluator,
                           const int ptex_face_index,
index 199b3a7c2f03a3af6f612e092d3359f7b6f288cc..469c949d1ca882be19daa128842f813b72a944d8 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 199b3a7c2f03a3af6f612e092d3359f7b6f288cc
+Subproject commit 469c949d1ca882be19daa128842f813b72a944d8
index 3683429de050b8026835d17ae7288a436c31cdb6..c88411ff7776a2db5d6ef6117a1b2faa42a95611 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 3683429de050b8026835d17ae7288a436c31cdb6
+Subproject commit c88411ff7776a2db5d6ef6117a1b2faa42a95611
index ca68e1d4e01d343b1758118b500bdc92eaea30ee..310578043dec1aae382eb6a447ae1d103792d7e6 160000 (submodule)
@@ -1 +1 @@
-Subproject commit ca68e1d4e01d343b1758118b500bdc92eaea30ee
+Subproject commit 310578043dec1aae382eb6a447ae1d103792d7e6
index bb92e070d00c2d398407607c2c849fd8adc830d2..3cdded79fd2cc3a048d579d44c4db7005e3755a0 100644 (file)
@@ -32,6 +32,7 @@ _modules = [
     "constraint",
     "file",
     "image",
+    "lanpr",
     "mask",
     "mesh",
     "node",
diff --git a/release/scripts/startup/bl_operators/lanpr.py b/release/scripts/startup/bl_operators/lanpr.py
new file mode 100644 (file)
index 0000000..6e89542
--- /dev/null
@@ -0,0 +1,241 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+import bpy
+import string
+
+GLOBAL_OUTPUT_PATH = ''
+
+def lanpr_get_composition_scene(scene):
+    n = scene.name+'_lanpr_comp'
+    for s in bpy.data.scenes:
+        if s.name == n: return s
+    return None
+
+def lanpr_make_composition_scene(scene):
+    name = scene.name;
+    new_name = scene.name+'_lanpr_comp'
+    scene.name = new_name
+    bpy.ops.scene.new(type='LINK_COPY')
+    for s in bpy.data.scenes:
+        if s.name == new_name+'.001':
+            new_scene = s
+            break
+    scene.name = name
+    new_scene.name = new_name
+    
+    s = new_scene
+    
+    s.render.engine = 'BLENDER_LANPR'
+    s.use_nodes = True
+    
+    comp = s.node_tree
+    
+    comp.nodes.clear()
+    n1 = comp.nodes.new("CompositorNodeRLayers")
+    n1.scene = scene
+    n1.location = (0,0)
+    n2 = comp.nodes.new("CompositorNodeRLayers")
+    n2.scene = s
+    n2.location = (0,-300)
+    
+    mix = comp.nodes.new("CompositorNodeAlphaOver")
+    mix.location = (300,-150)
+    comp.links.new(n1.outputs['Image'],mix.inputs[1])
+    comp.links.new(n2.outputs['Image'],mix.inputs[2])
+    
+    out = comp.nodes.new("CompositorNodeComposite")
+    out.location = (500,-150)
+    comp.links.new(mix.outputs['Image'],out.inputs['Image'])
+    
+    
+class LANPR_make_composition_scene(bpy.types.Operator):
+    """Make Composition Scene"""
+    bl_idname = "lanpr.make_composition_scene"
+    bl_label = "Make Composition Scene"
+
+    @classmethod
+    def poll(cls, context):
+        return (lanpr_get_composition_scene(context.scene) is None)
+
+    def execute(self, context):
+        lanpr_make_composition_scene(context.scene)
+        return {'FINISHED'}
+
+def lanpr_remove_composition_scene(scene):
+    bpy.data.scenes.remove(lanpr_get_composition_scene(scene))
+
+class LANPR_remove_composition_scene(bpy.types.Operator):
+    """Remove Composition Scene"""
+    bl_idname = "lanpr.remove_composition_scene"
+    bl_label = "Remove Composition Scene"
+
+    @classmethod
+    def poll(cls, context):
+        return (lanpr_get_composition_scene(context.scene) is not None)
+
+    def execute(self, context):
+        lanpr_remove_composition_scene(context.scene)
+        return {'FINISHED'}
+    
+def lanpr_is_composition_scene(scene):
+    return scene.name.endswith('_lanpr_comp')
+
+def lanpr_get_original_scene(scene):
+    name = scene.name[:-len('_lanpr_comp')]
+    for s in bpy.data.scenes:
+        if s.name == name: return s
+    return None
+
+def lanpr_goto_original_scene(scene):
+    s = lanpr_get_original_scene(scene)
+    if s: bpy.context.window.scene = s
+    
+            
+class LANPR_goto_original_scene(bpy.types.Operator):
+    """Goto Original Scene"""
+    bl_idname = "lanpr.goto_original_scene"
+    bl_label = "Goto Original Scene"
+
+    @classmethod
+    def poll(cls, context):
+        return lanpr_is_composition_scene(context.scene)
+
+    def execute(self, context):
+        lanpr_goto_original_scene(context.scene)
+        return {'FINISHED'}
+    
+def lanpr_goto_composition_scene(scene):
+    name = scene.name+'_lanpr_comp'
+    for s in bpy.data.scenes:
+        if s.name == name:
+            bpy.context.window.scene = s
+            break
+            
+class LANPR_goto_composition_scene(bpy.types.Operator):
+    """Goto Composition Scene"""
+    bl_idname = "lanpr.goto_composition_scene"
+    bl_label = "Goto Composition Scene"
+
+    @classmethod
+    def poll(cls, context):
+        return lanpr_get_composition_scene(context.scene) is not None
+
+    def execute(self, context):
+        lanpr_goto_composition_scene(context.scene)
+        return {'FINISHED'}
+
+
+#callbacks
+
+GC = None
+
+def lanpr_render_next_frame(sc):
+    global GLOBAL_OUTPUT_PATH
+    sc.frame_current = sc.frame_current+1
+    if sc.frame_current>sc.frame_end: 
+        bpy.app.handlers.render_complete.remove(lanpr_render_next_frame)
+        bpy.context.scene.render.filepath = GLOBAL_OUTPUT_PATH
+        return
+    
+    #bpy.app.handlers.render_cancel.append(lanpr_render_canceled)
+    #bpy.app.handlers.render_complete.remove(lanpr_render_next_frame)
+    
+    #lanpr_render_backdrop_first(sc)
+
+def lanpr_render_this_scene_next(scene):
+    
+    #bpy.app.handlers.render_complete.remove(lanpr_render_this_scene_next)
+    #bpy.app.handlers.render_cancel.remove(lanpr_render_canceled)
+    
+    #bpy.app.handlers.render_cancel.append(lanpr_render_canceled)
+    
+    sc = scene #lanpr_get_composition_scene(scene)
+    write = sc.lanpr.composite_render_animation
+    
+    bpy.context.scene.render.filepath = GLOBAL_OUTPUT_PATH + '/%04d'%sc.frame_current + bpy.context.scene.render.file_extension
+    
+    if sc.lanpr.composite_render_animation:
+        #bpy.app.handlers.render_complete.append(lanpr_render_next_frame)
+        global GC
+        bpy.ops.render.render(scene=sc.name, write_still = write)
+    else:
+        #'INVOKE_DEAFULT' still cause trouble on windows.
+        #bpy.ops.render.render(GC,'INVOKE_DEFAULT',scene=sc.name)
+        bpy.ops.render.render(scene=sc.name)
+    
+def lanpr_render_canceled(scene):
+    
+    bpy.app.handlers.render_complete.remove(lanpr_render_this_scene_next)
+    
+    bpy.app.handlers.render_cancel.remove(lanpr_render_canceled)
+
+def lanpr_render_backdrop_first(this_scene):
+    s = lanpr_get_original_scene(this_scene)
+    if not s: return
+
+    s.frame_current = this_scene.frame_current
+    #bpy.app.handlers.render_complete.append(lanpr_render_this_scene_next)
+    bpy.ops.render.render(scene=s.name)
+            
+class LANPR_render_composited(bpy.types.Operator):
+    """Render Composited"""
+    bl_idname = "lanpr.render_composited"
+    bl_label = "Render Composited"
+
+    @classmethod
+    def poll(cls, context):
+        return True
+    
+    def execute(self, context):
+        if bpy.context.scene.lanpr.composite_render_animation:
+            s = lanpr_get_original_scene(bpy.context.scene)
+            bpy.context.scene.frame_current = bpy.context.scene.frame_start
+            s.frame_current = bpy.context.scene.frame_start
+            bpy.context.scene.frame_end = s.frame_end
+            bpy.context.scene.render.filepath = s.render.filepath
+            
+        global GLOBAL_OUTPUT_PATH
+        GLOBAL_OUTPUT_PATH = bpy.context.scene.render.filepath
+
+        bpy.app.handlers.render_cancel.append(lanpr_render_canceled)
+        global GC
+        GC = bpy.context.copy()
+        
+        while True :
+        
+            lanpr_render_backdrop_first(bpy.context.scene)
+            
+            lanpr_render_this_scene_next(bpy.context.scene)
+            
+            bpy.context.scene.frame_current = bpy.context.scene.frame_current+1
+            if not bpy.context.scene.lanpr.composite_render_animation or bpy.context.scene.frame_current>bpy.context.scene.frame_end: 
+                bpy.context.scene.render.filepath = GLOBAL_OUTPUT_PATH
+                return {'FINISHED'}
+        
+        return {'FINISHED'}
+
+classes=(
+    LANPR_make_composition_scene,
+    LANPR_remove_composition_scene,
+    LANPR_goto_original_scene,
+    LANPR_goto_composition_scene,
+    LANPR_render_composited,
+)
\ No newline at end of file
index 668dd61315d60c461aecd4961fafbbe28d80a071..b490434bdb73b364ba9bc57ec452abc22596e6cc 100644 (file)
@@ -673,7 +673,32 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
             row.operator("object.multires_external_save", text="Save External...")
             row.label()
 
-    def OCEAN(self, layout, _ob, md):
+    def MY_BMESH(self, layout, ob, md):
+        split = layout.split(factor=0.25)
+
+        col = split.column()
+        col.label(text="§6.1:")
+        col.prop(md, "do_tri")
+        col.prop(md, "do_ff_bb_split")
+
+        col = split.column()
+        col.label(text="§6.2:")
+        col.prop(md, "do_cusp_dect")
+        col.prop(md, "do_insert")
+        col.prop(md, "do_cusp_insert")
+
+        col = split.column()
+        col.label(text="§6.3:")
+        col.prop(md, "do_rad_insert")
+        col.prop(md, "do_rad_flip")
+        col.prop(md, "do_opti")
+
+
+        col = layout.column()
+        col.label(text="Camera Object:")
+        col.prop(md, "camera_object", text="")
+
+    def OCEAN(self, layout, ob, md):
         if not bpy.app.build_options.mod_oceansim:
             layout.label(text="Built without OceanSim modifier")
             return
index 8817d35b88af437f4ca81c9be3ab71c48b3cc2db..620c489f62a90a5cbb493e7193d05a9bac7f4135 100644 (file)
@@ -65,7 +65,7 @@ class PhysicButtonsPanel:
 
 class PHYSICS_PT_fluid(PhysicButtonsPanel, Panel):
     bl_label = "Fluid"
-    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_LANPR'}
 
     @classmethod
     def poll(cls, context):
@@ -308,7 +308,7 @@ class PHYSICS_PT_domain_gravity(PhysicButtonsPanel, Panel):
     bl_label = "World"
     bl_parent_id = 'PHYSICS_PT_fluid'
     bl_options = {'DEFAULT_CLOSED'}
-    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_LANPR'}
 
     @classmethod
     def poll(cls, context):
@@ -391,7 +391,7 @@ class PHYSICS_PT_domain_boundary(PhysicButtonsPanel, Panel):
     bl_label = "Boundary"
     bl_parent_id = 'PHYSICS_PT_fluid'
     bl_options = {'DEFAULT_CLOSED'}
-    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_LANPR'}
 
     @classmethod
     def poll(cls, context):
@@ -425,7 +425,7 @@ class PHYSICS_PT_domain_particles(PhysicButtonsPanel, Panel):
     bl_label = "Particles"
     bl_parent_id = 'PHYSICS_PT_fluid'
     bl_options = {'DEFAULT_CLOSED'}
-    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
+    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_LANPR'}
 
     @classmethod
     def poll(cls, context):
index df431000048fba3c599dfdf918ea812e4bf87085..3a12b89916b560bd8c3c5bd99ec946928dd98e43 100644 (file)
@@ -164,8 +164,8 @@ class SCENE_PT_keying_sets(SceneButtonsPanel, SceneKeyingSetsPanel, Panel):
         col.template_list("UI_UL_list", "keying_sets", scene, "keying_sets", scene.keying_sets, "active_index", rows=1)
 
         col = row.column(align=True)
-        col.operator("anim.keying_set_add", icon='ADD', text="")
-        col.operator("anim.keying_set_remove", icon='REMOVE', text="")
+        col.operator("anim.keying_set_add", icon='ZOOMIN', text="")
+        col.operator("anim.keying_set_remove", icon='ZOOMOUT', text="")
 
         layout.use_property_split = True
         layout.use_property_decorate = False  # No animation.
@@ -242,8 +242,8 @@ class SCENE_PT_keying_set_paths(SceneButtonsPanel, SceneKeyingSetsPanel, Panel):
         col.template_list("SCENE_UL_keying_set_paths", "", ks, "paths", ks.paths, "active_index", rows=1)
 
         col = row.column(align=True)
-        col.operator("anim.keying_set_path_add", icon='ADD', text="")
-        col.operator("anim.keying_set_path_remove", icon='REMOVE', text="")
+        col.operator("anim.keying_set_path_add", icon='ZOOMIN', text="")
+        col.operator("anim.keying_set_path_remove", icon='ZOOMOUT', text="")
 
         # TODO: 1) the template_any_ID needs to be fixed for the text alignment.
         #       2) use_property_decorate has to properly skip the non animatable properties.
@@ -280,6 +280,62 @@ class SCENE_PT_keying_set_paths(SceneButtonsPanel, SceneKeyingSetsPanel, Panel):
                 col.prop(ksp, "group")
 
 
+class SCENE_PT_color_management(SceneButtonsPanel, Panel):
+    bl_label = "Color Management"
+    bl_options = {'DEFAULT_CLOSED'}
+    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL', 'BLENDER_LANPR'}
+
+    def draw(self, context):
+        layout = self.layout
+        layout.use_property_split = True
+
+        scene = context.scene
+        view = scene.view_settings
+
+        flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
+
+        col = flow.column()
+        col.prop(scene.display_settings, "display_device")
+
+        col.separator()
+
+        col.prop(view, "view_transform")
+        col.prop(view, "look")
+
+        col = flow.column()
+        col.prop(view, "exposure")
+        col.prop(view, "gamma")
+
+        col.separator()
+
+        col.prop(scene.sequencer_colorspace_settings, "name", text="Sequencer")
+
+
+class SCENE_PT_color_management_curves(SceneButtonsPanel, Panel):
+    bl_label = "Use Curves"
+    bl_parent_id = "SCENE_PT_color_management"
+    bl_options = {'DEFAULT_CLOSED'}
+    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL', 'BLENDER_LANPR'}
+
+    def draw_header(self, context):
+
+        scene = context.scene
+        view = scene.view_settings
+
+        self.layout.prop(view, "use_curve_mapping", text="")
+
+    def draw(self, context):
+        layout = self.layout
+
+        scene = context.scene
+        view = scene.view_settings
+
+        layout.use_property_split = False
+        layout.enabled = view.use_curve_mapping
+
+        layout.template_curve_mapping(view, "curve_mapping", levels=True)
+
+
 class SCENE_PT_audio(SceneButtonsPanel, Panel):
     bl_label = "Audio"
     bl_options = {'DEFAULT_CLOSED'}
@@ -423,6 +479,492 @@ class SCENE_PT_rigid_body_field_weights(RigidBodySubPanel, Panel):
         effector_weights_ui(self, rbw.effector_weights, 'RIGID_BODY')
 
 
+class SCENE_PT_simplify(SceneButtonsPanel, Panel):
+    bl_label = "Simplify"
+    bl_options = {'DEFAULT_CLOSED'}
+    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL', 'BLENDER_LANPR'}
+
+    def draw_header(self, context):
+        rd = context.scene.render
+        self.layout.prop(rd, "use_simplify", text="")
+
+    def draw(self, context):
+        pass
+
+
+class SCENE_PT_simplify_viewport(SceneButtonsPanel, Panel):
+    bl_label = "Viewport"
+    bl_parent_id = "SCENE_PT_simplify"
+    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL', 'BLENDER_LANPR'}
+
+    def draw(self, context):
+        layout = self.layout
+        layout.use_property_split = True
+
+        rd = context.scene.render
+
+        layout.active = rd.use_simplify
+
+        flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
+
+        col = flow.column()
+        col.prop(rd, "simplify_subdivision", text="Max Subdivision")
+
+        col = flow.column()
+        col.prop(rd, "simplify_child_particles", text="Max Child Particles")
+
+
+class SCENE_PT_simplify_render(SceneButtonsPanel, Panel):
+    bl_label = "Render"
+    bl_parent_id = "SCENE_PT_simplify"
+    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL', 'BLENDER_LANPR'}
+
+    def draw(self, context):
+        layout = self.layout
+        layout.use_property_split = True
+
+        rd = context.scene.render
+
+        layout.active = rd.use_simplify
+
+        flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
+
+        col = flow.column()
+        col.prop(rd, "simplify_subdivision_render", text="Max Subdivision")
+
+        col = flow.column()
+        col.prop(rd, "simplify_child_particles_render", text="Max Child Particles")
+
+
+class SCENE_PT_simplify_greasepencil(SceneButtonsPanel, Panel):
+    bl_label = "Grease Pencil"
+    bl_parent_id = "SCENE_PT_simplify"
+    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY', 'BLENDER_EEVEE'}
+    bl_options = {'DEFAULT_CLOSED'}
+
+    def draw_header(self, context):
+        rd = context.scene.render
+        self.layout.prop(rd, "simplify_gpencil", text="")
+
+    def draw(self, context):
+        layout = self.layout
+        layout.use_property_split = True
+
+        rd = context.scene.render
+
+        layout.active = rd.simplify_gpencil
+
+        col = layout.column()
+        col.prop(rd, "simplify_gpencil_onplay", text="Playback Only")
+        col.prop(rd, "simplify_gpencil_view_modifier", text="Modifiers")
+        col.prop(rd, "simplify_gpencil_shader_fx", text="ShaderFX")
+
+        col = layout.column(align=True)
+        col.prop(rd, "simplify_gpencil_view_fill")
+        sub = col.column()
+        sub.active = rd.simplify_gpencil_view_fill
+        sub.prop(rd, "simplify_gpencil_remove_lines", text="Lines")
+
+class SCENE_PT_viewport_display(SceneButtonsPanel, Panel):
+    bl_label = "Viewport Display"
+    bl_options = {'DEFAULT_CLOSED'}
+
+    @classmethod
+    def poll(cls, context):
+        return True
+
+    def draw(self, context):
+        layout = self.layout
+        layout.use_property_split = True
+        scene = context.scene
+        col = layout.column()
+        col.prop(scene.display, "light_direction")
+        col.prop(scene.display, "shadow_shift")
+
+class LANPR_linesets(UIList):
+    def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+        lineset = item
+        if self.layout_type in {'DEFAULT', 'COMPACT'}:
+            split = layout.split(factor=0.6)
+            split.label(text="Layer")
+            row = split.row(align=True)
+            row.prop(lineset, "color", text="", icon_value=icon)
+            row.prop(lineset, "thickness", text="", icon_value=icon)
+        elif self.layout_type == 'GRID':
+            layout.alignment = 'CENTER'
+            layout.label("", icon_value=icon)
+
+def lanpr_get_composition_scene(scene):
+    n = scene.name+'_lanpr_comp'
+    for s in bpy.data.scenes:
+        if s.name == n: return s
+    return None
+
+def lanpr_is_composition_scene(scene):
+    return scene.name.endswith('_lanpr_comp')
+
+class SCENE_PT_lanpr(SceneButtonsPanel, Panel):
+    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_LANPR', 'BLENDER_OPENGL', 'BLENDER_EEVEE'}
+    bl_label = "LANPR"
+    bl_options = {'DEFAULT_CLOSED'}
+    
+    @classmethod
+    def poll(cls, context):
+        return True
+
+    def draw(self, context):
+        layout = self.layout
+        scene = context.scene
+        lanpr = scene.lanpr
+        active_layer = lanpr.layers.active_layer 
+        
+        sc = lanpr_get_composition_scene(scene)
+        
+        if sc is not None:
+            layout.label(text = 'You are adjusting values for LANPR compostion scene.')
+            row = layout.row()
+            row.scale_y=1.5
+            row.operator("lanpr.goto_composition_scene")
+            layout.operator("lanpr.remove_composition_scene")
+            scene = sc
+            lanpr = scene.lanpr
+            active_layer = lanpr.layers.active_layer
+            return
+        elif scene.render.engine!='BLENDER_LANPR':
+            layout.label(text = 'Select LANPR engine or use composition scene.')
+            layout.operator("lanpr.make_composition_scene")
+            return
+
+        if lanpr_is_composition_scene(scene):
+            row = layout.row()
+            row.scale_y=1.5
+            row.operator("lanpr.goto_original_scene") 
+            
+            layout.label(text='LANPR Composition')
+            row = layout.row()
+            row.scale_y=1.5
+            row.scale_x=4
+            row.operator("lanpr.render_composited", icon = 'RENDER_STILL')
+            row.scale_x=1
+            row.prop(lanpr,"composite_render_animation", toggle=True, icon = 'RENDER_ANIMATION')
+        
+        layout.label(text='Mode:')
+        
+        layout.prop(lanpr, "master_mode", expand=True) 
+
+        if lanpr.master_mode == "DPIX" or lanpr.master_mode == "SOFTWARE":
+            
+            layout.prop(lanpr, "background_color")
+
+            if lanpr.master_mode == "SOFTWARE":
+                layout.label(text="Enable On Demand:")
+                row = layout.row()
+                row.prop(lanpr,"enable_intersections", text = "Intersection Lines")
+                row.prop(lanpr,"enable_chaining", text = "Chaining (SLOW!)")
+                layout.label(text="RUN:")
+                layout.operator("scene.lanpr_calculate", icon='RENDER_STILL')
+
+                split = layout.split(factor=0.7)
+                col = split.column()
+                col.label(text="Layer Composition:")
+                col = split.column()
+                col.operator("scene.lanpr_auto_create_line_layer", text = "Default")#, icon = "ZOOMIN")
+                layout.template_list("LANPR_linesets", "", lanpr, "layers", lanpr.layers, "active_layer_index", rows=4)
+                if active_layer:
+                    split = layout.split()
+                    col = split.column()
+                    col.operator("scene.lanpr_add_line_layer")#icon="ZOOMIN")
+                    col.operator("scene.lanpr_delete_line_layer")#, icon="ZOOMOUT")
+                    col = split.column()
+                    col.operator("scene.lanpr_move_line_layer").direction = "UP"
+                    col.operator("scene.lanpr_move_line_layer").direction = "DOWN"
+                    layout.operator("scene.lanpr_rebuild_all_commands")
+                else:
+                    layout.operator("scene.lanpr_add_line_layer")
+            
+            if active_layer:
+                layout.label(text= "Normal:")
+                layout.prop(active_layer,"normal_mode", expand = True)
+                if active_layer.normal_mode != "DISABLED":
+                    layout.prop(active_layer,"normal_control_object")
+                    layout.prop(active_layer,"normal_effect_inverse", toggle = True)
+                    layout.prop(active_layer,"normal_ramp_begin")
+                    layout.prop(active_layer,"normal_ramp_end")
+                    layout.prop(active_layer,"normal_thickness_begin", slider=True)
+                    layout.prop(active_layer,"normal_thickness_end", slider=True)
+            
+        else:
+            layout.label(text="Vectorization:")
+            layout.prop(lanpr, "enable_vector_trace", expand = True)
+
+
+class SCENE_PT_lanpr_line_types(SceneButtonsPanel, Panel):
+    bl_label = "Types"
+    bl_parent_id = "SCENE_PT_lanpr"
+    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_LANPR', 'BLENDER_OPENGL'}
+
+    @classmethod
+    def poll(cls, context):
+        scene = context.scene
+        lanpr = scene.lanpr
+        active_layer = lanpr.layers.active_layer
+        return active_layer and lanpr.master_mode != "SNAKE"
+
+    def draw(self, context):
+        layout = self.layout
+        scene = context.scene
+        lanpr = scene.lanpr
+        active_layer = lanpr.layers.active_layer
+        if active_layer and lanpr.master_mode == "DPIX":
+            active_layer = lanpr.layers[0]
+
+        layout.operator("scene.lanpr_enable_all_line_types")
+
+        split = layout.split(factor=0.3)
+        col = split.column()
+        col.prop(active_layer, "enable_contour", text="Contour", toggle=True)
+        col.prop(active_layer, "enable_crease", text="Crease", toggle=True)
+        col.prop(active_layer, "enable_edge_mark", text="Mark", toggle=True)
+        col.prop(active_layer, "enable_material_seperate", text="Material", toggle=True)
+        col.prop(active_layer, "enable_intersection", text="Intersection", toggle=True)
+        col = split.column()
+        row = col.row(align = True)
+        #row.enabled = active_layer.enable_contour this is always enabled now
+        row.prop(active_layer, "color", text="")
+        row.prop(active_layer, "thickness", text="")
+        row = col.row(align = True)
+        row.enabled = active_layer.enable_crease
+        row.prop(active_layer, "crease_color", text="")
+        row.prop(active_layer, "thickness_crease", text="")
+        row = col.row(align = True)
+        row.enabled = active_layer.enable_edge_mark
+        row.prop(active_layer, "edge_mark_color", text="")
+        row.prop(active_layer, "thickness_edge_mark", text="")
+        row = col.row(align = True)
+        row.enabled = active_layer.enable_material_seperate
+        row.prop(active_layer, "material_color", text="")
+        row.prop(active_layer, "thickness_material", text="")
+        row = col.row(align = True)
+        if lanpr.enable_intersections:
+            row.enabled = active_layer.enable_intersection
+            row.prop(active_layer, "intersection_color", text="")
+            row.prop(active_layer, "thickness_intersection", text="")
+        else:
+            row.label(text= "Intersection Calculation Disabled")
+
+        if lanpr.master_mode == "DPIX" and active_layer.enable_intersection:
+            row = col.row(align = True)
+            row.prop(lanpr,"enable_intersections", toggle = True, text = "Enable")
+            if lanpr.enable_intersections:
+                row.operator("scene.lanpr_calculate", text= "Recalculate")
+
+        if lanpr.master_mode == "SOFTWARE":
+            row = layout.row(align=True)
+            row.prop(active_layer, "qi_begin")
+            row.prop(active_layer, "qi_end")
+
+class SCENE_PT_lanpr_line_components(SceneButtonsPanel, Panel):
+    bl_label = "Including"
+    bl_parent_id = "SCENE_PT_lanpr"
+    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_LANPR', 'BLENDER_OPENGL'}
+
+    @classmethod
+    def poll(cls, context):
+        scene = context.scene
+        lanpr = scene.lanpr
+        active_layer = lanpr.layers.active_layer
+        return active_layer and lanpr.master_mode == "SOFTWARE" and not lanpr.enable_chaining
+
+    def draw(self, context):
+        layout = self.layout
+        scene = context.scene
+        lanpr = scene.lanpr
+        active_layer = lanpr.layers.active_layer
+
+        layout.operator("scene.lanpr_add_line_component")#, icon = "ZOOMIN")
+        
+        i=0
+        for c in active_layer.components:
+            split = layout.split(factor=0.85)
+            col = split.column()
+            sp2 = col.split(factor=0.4)
+            cl = sp2.column()
+            cl.prop(c,"component_mode", text = "")
+            cl = sp2.column()
+            if c.component_mode == "OBJECT":
+                cl.prop(c,"object_select", text = "")
+            elif c.component_mode == "MATERIAL":
+                cl.prop(c,"material_select", text = "")
+            elif c.component_mode == "COLLECTION":
+                cl.prop(c,"collection_select", text = "")
+            col = split.column()
+            col.operator("scene.lanpr_delete_line_component", text="").index=i
+            i=i+1
+
+
+class SCENE_PT_lanpr_line_effects(SceneButtonsPanel, Panel):
+    bl_label = "Effects"
+    bl_parent_id = "SCENE_PT_lanpr"
+    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_LANPR', 'BLENDER_OPENGL'}
+
+    @classmethod
+    def poll(cls, context):
+        scene = context.scene
+        lanpr = scene.lanpr
+        return lanpr.master_mode == "DPIX"
+
+    def draw(self, context):
+        layout = self.layout
+        scene = context.scene
+        lanpr = scene.lanpr
+        active_layer = lanpr.layers.active_layer
+
+        row = layout.row(align = True)
+        row.prop(lanpr, "crease_threshold")
+        row.prop(lanpr, "crease_fade_threshold")
+        row = layout.row(align = True)
+        row.prop(lanpr, "depth_width_influence")
+        row.prop(lanpr, "depth_width_curve")
+        row = layout.row(align = True)
+        row.prop(lanpr, "depth_alpha_influence")
+        row.prop(lanpr, "depth_alpha_curve")
+
+class SCENE_PT_lanpr_snake_sobel_parameters(SceneButtonsPanel, Panel):
+    bl_label = "Sobel Parameters"
+    bl_parent_id = "SCENE_PT_lanpr"
+    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_LANPR', 'BLENDER_OPENGL'}
+
+    @classmethod
+    def poll(cls, context):
+        scene = context.scene
+        lanpr = scene.lanpr
+        return lanpr.master_mode == "SNAKE"
+
+    def draw(self, context):
+        layout = self.layout
+        scene = context.scene
+        lanpr = scene.lanpr
+        layout.prop(lanpr, "depth_clamp")
+        layout.prop(lanpr, "depth_strength")
+        layout.prop(lanpr, "normal_clamp")
+        layout.prop(lanpr, "normal_strength")
+        if lanpr.enable_vector_trace == "DISABLED":
+            layout.prop(lanpr, "display_thinning_result")
+
+class SCENE_PT_lanpr_snake_settings(SceneButtonsPanel, Panel):
+    bl_label = "Snake Settings"
+    bl_parent_id = "SCENE_PT_lanpr"
+    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_LANPR', 'BLENDER_OPENGL'}
+
+    @classmethod
+    def poll(cls, context):
+        scene = context.scene
+        lanpr = scene.lanpr
+        return lanpr.master_mode == "SNAKE" and lanpr.enable_vector_trace == "ENABLED"
+
+    def draw(self, context):
+        layout = self.layout
+        scene = context.scene
+        lanpr = scene.lanpr
+
+        split = layout.split()
+        col = split.column()
+        col.prop(lanpr, "background_color")
+        col = split.column()
+        col.prop(lanpr, "line_color")
+        
+        layout.prop(lanpr, "line_thickness")
+
+        split = layout.split()
+        col = split.column()
+        col.prop(lanpr, "depth_width_influence")
+        col.prop(lanpr, "depth_alpha_influence")
+        col = split.column()
+        col.prop(lanpr, "depth_width_curve")
+        col.prop(lanpr, "depth_alpha_curve")
+        
+        layout.label(text="Taper:")
+        layout.prop(lanpr, "use_same_taper", expand = True)
+        if lanpr.use_same_taper == "DISABLED":
+            split = layout.split()
+            col = split.column(align = True)
+            col.label(text="Left:")
+            col.prop(lanpr,"taper_left_distance")
+            col.prop(lanpr,"taper_left_strength")
+            col = split.column(align = True)
+            col.label(text="Right:")
+            col.prop(lanpr,"taper_right_distance")
+            col.prop(lanpr,"taper_right_strength")
+        else:
+            split = layout.split()
+            col = split.column(align = True)
+            col.prop(lanpr,"taper_left_distance")
+            col.prop(lanpr,"taper_left_strength") 
+
+        layout.label(text="Tip Extend:")
+        layout.prop(lanpr, "enable_tip_extend",  expand = True)
+        if lanpr.enable_tip_extend == "ENABLED":
+            layout.label(text="---INOP---")
+            layout.prop(lanpr,"extend_length")
+
+class SCENE_PT_lanpr_software_chain_styles(SceneButtonsPanel, Panel):
+    bl_label = "Chain Styles"
+    bl_parent_id = "SCENE_PT_lanpr"
+    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_LANPR', 'BLENDER_OPENGL'}
+
+    @classmethod
+    def poll(cls, context):
+        scene = context.scene
+        lanpr = scene.lanpr
+        return lanpr.master_mode == "SOFTWARE" and lanpr.enable_chaining
+
+    def draw(self, context):
+        layout = self.layout
+        scene = context.scene
+        lanpr = scene.lanpr
+        layout.label(text="Taper:")
+        layout.prop(lanpr, "use_same_taper", expand = True)
+        if lanpr.use_same_taper == "DISABLED":
+            split = layout.split()
+            col = split.column(align = True)
+            col.label(text="Left:")
+            col.prop(lanpr,"taper_left_distance")
+            col.prop(lanpr,"taper_left_strength")
+            col = split.column(align = True)
+            col.label(text="Right:")
+            col.prop(lanpr,"taper_right_distance")
+            col.prop(lanpr,"taper_right_strength")
+        else:
+            split = layout.split()
+            col = split.column(align = True)
+            col.prop(lanpr,"taper_left_distance")
+            col.prop(lanpr,"taper_left_strength") 
+
+        layout.label(text="Tip Extend:")
+        layout.prop(lanpr, "enable_tip_extend",  expand = True)
+        if lanpr.enable_tip_extend == "ENABLED":
+            layout.label(text="---INOP---")
+            layout.prop(lanpr,"extend_length")
+
+
+class SCENE_PT_viewport_display_ssao(SceneButtonsPanel, Panel):
+    bl_label = "Screen Space Ambient Occlusion"
+    bl_parent_id = "SCENE_PT_viewport_display"
+
+    @classmethod
+    def poll(cls, context):
+        return True
+
+    def draw(self, context):
+        layout = self.layout
+        layout.use_property_split = True
+        scene = context.scene
+        col = layout.column()
+        col.prop(scene.display, "matcap_ssao_samples")
+        col.prop(scene.display, "matcap_ssao_distance")
+        col.prop(scene.display, "matcap_ssao_attenuation")
+
+
 class SCENE_PT_custom_props(SceneButtonsPanel, PropertyPanel, Panel):
     _context_path = "scene"
     _property_type = bpy.types.Scene
@@ -432,16 +974,34 @@ classes = (
     SCENE_UL_keying_set_paths,
     SCENE_PT_scene,
     SCENE_PT_unit,
-    SCENE_PT_physics,
     SCENE_PT_keying_sets,
     SCENE_PT_keying_set_paths,
     SCENE_PT_keyframing_settings,
+    SCENE_PT_color_management,
+    SCENE_PT_color_management_curves,
+    SCENE_PT_viewport_display,
+    SCENE_PT_viewport_display_ssao,
     SCENE_PT_audio,
+    SCENE_PT_physics,
     SCENE_PT_rigid_body_world,
     SCENE_PT_rigid_body_world_settings,
     SCENE_PT_rigid_body_cache,
     SCENE_PT_rigid_body_field_weights,
+    SCENE_PT_simplify,
+    SCENE_PT_simplify_viewport,
+    SCENE_PT_simplify_render,
+    SCENE_PT_simplify_greasepencil,
     SCENE_PT_custom_props,
+
+    SCENE_PT_lanpr,
+    SCENE_PT_lanpr_line_types,
+    SCENE_PT_lanpr_line_components,
+    SCENE_PT_lanpr_line_effects,
+    SCENE_PT_lanpr_snake_sobel_parameters,
+    SCENE_PT_lanpr_snake_settings,
+    SCENE_PT_lanpr_software_chain_styles,
+
+    LANPR_linesets,
 )
 
 if __name__ == "__main__":  # only for live edit.
index f572362b02b531f5e7852a429959a7ae8433e550..e5a8b283af0c62d2c9a82e1f89dc37a978fbd630 100644 (file)
@@ -3594,6 +3594,7 @@ class VIEW3D_MT_edit_mesh_edges_data(Menu):
         if render.use_freestyle:
             layout.separator()
 
+        #if with_freestyle:     we still presere freestyle mark functions.
             layout.operator("mesh.mark_freestyle_edge").clear = False
             layout.operator("mesh.mark_freestyle_edge", text="Clear Freestyle Edge").clear = True
 
index 5fad95c54e2d21ab569d35ea7610b4fe5dc491e3..ee85ce40f2a973e114bb27679cdcb296c5029f4d 100644 (file)
@@ -961,6 +961,29 @@ void BKE_scene_init(Scene *sce)
   sce->eevee.flag = SCE_EEVEE_VOLUMETRIC_LIGHTS | SCE_EEVEE_GTAO_BENT_NORMALS |
                     SCE_EEVEE_GTAO_BOUNCE | SCE_EEVEE_TAA_REPROJECTION |
                     SCE_EEVEE_SSR_HALF_RESOLUTION;
+
+       /* SceneLANPR */
+       
+       sce->lanpr.crease_threshold = 0.7;
+
+       sce->lanpr.line_thickness = 1.5;
+       sce->lanpr.depth_clamp = 0.001;
+       sce->lanpr.depth_strength = 800;
+       sce->lanpr.normal_clamp = 2;
+       sce->lanpr.normal_strength = 10;
+       
+       sce->lanpr.enable_intersections = 1;
+
+       sce->lanpr.background_color[0] = 0.76;
+       sce->lanpr.background_color[1] = 0.54;
+       sce->lanpr.background_color[2] = 0.29;
+       sce->lanpr.background_color[3] = 1;
+
+       sce->lanpr.line_color[0] = 0.39;
+       sce->lanpr.line_color[1] = 0.12;
+       sce->lanpr.line_color[2] = 0.04;
+       sce->lanpr.line_color[3] = 1;
+
 }
 
 Scene *BKE_scene_add(Main *bmain, const char *name)
index 6e3c459ddda4034bc0951cea929e39d499a8d425..eb37078f6817781a980337c5c8f8cb254f98e6ad 100644 (file)
@@ -78,6 +78,7 @@
 #include "DNA_packedFile_types.h"
 #include "DNA_particle_types.h"
 #include "DNA_lightprobe_types.h"
+#include "DNA_lanpr_types.h"
 #include "DNA_rigidbody_types.h"
 #include "DNA_text_types.h"
 #include "DNA_view3d_types.h"
@@ -6583,6 +6584,16 @@ static void lib_link_scene(FileData *fd, Main *main)
           fls->group = newlibadr_us(fd, sce->id.lib, fls->group);
         }
       }
+
+                       for (LANPR_LineLayer *ll = sce->lanpr.line_layers.first; ll; ll = ll->next) {
+                               for (LANPR_LineLayerComponent *llc = ll->components.first; llc; llc = llc->next) {
+                                       llc->object_select = newlibadr_us(fd, sce->id.lib, llc->object_select);
+                                       llc->material_select = newlibadr_us(fd, sce->id.lib, llc->material_select);
+                                       llc->collection_select = newlibadr_us(fd, sce->id.lib, llc->collection_select);
+                               }
+                               ll->normal_control_object = newlibadr_us(fd, sce->id.lib, ll->normal_control_object);
+                       }
+
       /* Motion Tracking */
       sce->clip = newlibadr_us(fd, sce->id.lib, sce->clip);
 
@@ -7006,6 +7017,22 @@ static void direct_link_scene(FileData *fd, Scene *sce)
     }
   }
 
+       /* LANPR things */
+       sce->lanpr.active_layer = newdataadr(fd, sce->lanpr.active_layer);
+       sce->lanpr.render_buffer = NULL;
+       link_list(fd, &sce->lanpr.line_layers);
+       for (LANPR_LineLayer *ll = sce->lanpr.line_layers.first; ll; ll = ll->next) {
+               link_list(fd, &ll->components);
+               for(LANPR_LineLayerComponent *llc = ll->components.first; llc;llc=llc->next){
+                       //llc->object_select = newlibadr(fd, sce->id.lib, llc->object_select);
+                       //llc->material_select = newlibadr(fd, sce->id.lib, llc->material_select);
+                       //llc->collection_select = newlibadr(fd, sce->id.lib, llc->collection_select);
+               }
+               ll->batch = NULL;
+               ll->shgrp = NULL;
+               //ll->normal_control_object = newlibadr(fd, sce->id.lib, ll->normal_control_object);
+       }
+
   sce->layer_properties = newdataadr(fd, sce->layer_properties);
   IDP_DirectLinkGroup_OrFree(&sce->layer_properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
 }
@@ -10557,6 +10584,8 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
   SceneRenderLayer *srl;
   FreestyleModuleConfig *module;
   FreestyleLineSet *lineset;
+       LANPR_LineLayer* ll;
+       LANPR_LineLayerComponent* llc;
 
   for (Base *base_legacy = sce->base.first; base_legacy; base_legacy = base_legacy->next) {
     expand_doit(fd, mainvar, base_legacy->object);
@@ -10604,6 +10633,15 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
     }
   }
 
+       for (LANPR_LineLayer *ll = sce->lanpr.line_layers.first; ll; ll = ll->next) {
+               for (LANPR_LineLayerComponent *llc = ll->components.first; llc; llc = llc->next) {
+                       if (llc->object_select) expand_doit(fd, mainvar, llc->object_select);
+                       if (llc->material_select) expand_doit(fd, mainvar, llc->material_select);
+                       if (llc->collection_select) expand_doit(fd, mainvar, llc->collection_select);
+               }
+               if (ll->normal_control_object) expand_doit(fd, mainvar, ll->normal_control_object);
+       }
+
   if (sce->gpd)
     expand_doit(fd, mainvar, sce->gpd);
 
index e43553cd64ffadfb801497e21271911a5e0d04f4..d832967a329d61a637ed68bb094816515c392f67 100644 (file)
@@ -1625,6 +1625,32 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
       }
     }
 
+               if (!DNA_struct_find(fd->filesdna, "SceneLANPR")) {
+                       for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
+
+                               scene->lanpr.crease_threshold = 0.7;
+
+                               scene->lanpr.line_thickness = 1.5;
+                               scene->lanpr.depth_clamp = 0.001;
+                               scene->lanpr.depth_strength = 800;
+                               scene->lanpr.normal_clamp = 2;
+                               scene->lanpr.normal_strength = 10;
+                               
+                               scene->lanpr.enable_intersections = 1;
+                               
+                               scene->lanpr.background_color[0] = 0.76;
+                               scene->lanpr.background_color[1] = 0.54;
+                               scene->lanpr.background_color[2] = 0.29;
+                               scene->lanpr.background_color[3] = 1;
+                               
+                               scene->lanpr.line_color[0] = 0.39;
+                               scene->lanpr.line_color[1] = 0.12;
+                               scene->lanpr.line_color[2] = 0.04;
+                               scene->lanpr.line_color[3] = 1;
+
+                       }
+               }
+
     if (!MAIN_VERSION_ATLEAST(bmain, 280, 15)) {
       for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
         scene->display.matcap_ssao_distance = 0.2f;
index 79cd7678f906787a147ff58d7d9a4f9813953e11..33c89b3b3e63d90c5b86bc505780b76372003eb0 100644 (file)
 #include "DNA_packedFile_types.h"
 #include "DNA_particle_types.h"
 #include "DNA_lightprobe_types.h"
+#include "DNA_lanpr_types.h"
 #include "DNA_rigidbody_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_sdna_types.h"
@@ -2720,6 +2721,14 @@ static void write_scene(WriteData *wd, Scene *sce)
     write_lightcache(wd, sce->eevee.light_cache);
   }
 
+       /* LANPR Line Layers */
+       for (LANPR_LineLayer *ll = sce->lanpr.line_layers.first; ll; ll = ll->next) {
+               writestruct(wd, DATA, LANPR_LineLayer, 1, ll);
+               for (LANPR_LineLayerComponent *llc = ll->components.first; llc; llc = llc->next) {
+                       writestruct(wd, DATA, LANPR_LineLayerComponent, 1, llc);
+               }
+       }
+
   /* Freed on doversion. */
   BLI_assert(sce->layer_properties == NULL);
 }
index 0d1752af4dc8c6564118f02a2607a9981c45d38d..13888167d2ce3b6f65c2caa9a73a0f6757c364a6 100644 (file)
@@ -126,6 +126,13 @@ set(SRC
   engines/gpencil/gpencil_engine.h
   engines/gpencil/gpencil_render.c
   engines/gpencil/gpencil_shader_fx.c
+       engines/lanpr/lanpr_dpix.c
+       engines/lanpr/lanpr_engine.c
+       engines/lanpr/lanpr_snake.c
+       engines/lanpr/lanpr_ops.c
+       engines/lanpr/lanpr_util.c
+       engines/lanpr/lanpr_chain.c
+
 
   DRW_engine.h
   intern/DRW_render.h
@@ -149,6 +156,8 @@ set(SRC
   engines/external/external_engine.h
   engines/workbench/workbench_engine.h
   engines/workbench/workbench_private.h
+       engines/lanpr/lanpr_util.h
+       engines/lanpr/lanpr_all.h
 )
 
 set(LIB
@@ -246,6 +255,21 @@ data_to_c_simple(engines/workbench/shaders/workbench_volume_vert.glsl SRC)
 data_to_c_simple(engines/workbench/shaders/workbench_volume_frag.glsl SRC)
 data_to_c_simple(engines/workbench/shaders/workbench_world_light_lib.glsl SRC)
 
+data_to_c_simple(engines/lanpr/shaders/lanpr_dpix_preview_geom.glsl SRC)
+data_to_c_simple(engines/lanpr/shaders/lanpr_dpix_preview_frag.glsl SRC)
+data_to_c_simple(engines/lanpr/shaders/lanpr_dpix_project_clip_frag.glsl SRC)
+data_to_c_simple(engines/lanpr/shaders/lanpr_dpix_project_passthrough_vert.glsl SRC)
+data_to_c_simple(engines/lanpr/shaders/lanpr_snake_image_peel_frag.glsl SRC)
+data_to_c_simple(engines/lanpr/shaders/lanpr_snake_line_connection_vert.glsl SRC)
+data_to_c_simple(engines/lanpr/shaders/lanpr_snake_line_connection_geom.glsl SRC)
+data_to_c_simple(engines/lanpr/shaders/lanpr_snake_line_connection_frag.glsl SRC)
+data_to_c_simple(engines/lanpr/shaders/lanpr_snake_edge_frag.glsl SRC)
+data_to_c_simple(engines/lanpr/shaders/lanpr_snake_multichannel_frag.glsl SRC)
+data_to_c_simple(engines/lanpr/shaders/lanpr_software_line_chain_geom.glsl SRC)
+data_to_c_simple(engines/lanpr/shaders/lanpr_software_passthrough_vert.glsl SRC)
+data_to_c_simple(engines/lanpr/shaders/lanpr_software_chain_geom.glsl SRC)
+
+
 data_to_c_simple(modes/shaders/common_globals_lib.glsl SRC)
 data_to_c_simple(modes/shaders/common_hair_lib.glsl SRC)
 data_to_c_simple(modes/shaders/common_hair_refine_vert.glsl SRC)
diff --git a/source/blender/draw/engines/lanpr/lanpr_all.h b/source/blender/draw/engines/lanpr/lanpr_all.h
new file mode 100644 (file)
index 0000000..7ba0687
--- /dev/null
@@ -0,0 +1,819 @@
+#pragma once
+
+#include "lanpr_util.h"
+#include "BLI_mempool.h"
+#include "BLI_utildefines.h"
+//#include "GPU_framebuffer.h"
+#include "GPU_batch.h"
+#include "GPU_framebuffer.h"
+#include "GPU_shader.h"
+#include "GPU_uniformbuffer.h"
+#include "GPU_viewport.h"
+#include "DNA_listBase.h"
+#include "DRW_render.h"
+#include "BKE_object.h"
+#include "DNA_mesh_types.h"
+#include "DNA_camera_types.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_framebuffer.h"
+#include "DNA_lanpr_types.h"
+#include "DNA_meshdata_types.h"
+#include "BKE_customdata.h"
+#include "DEG_depsgraph_query.h"
+#include "GPU_draw.h"
+
+#include "BLI_threads.h"
+
+#include "GPU_batch.h"
+#include "GPU_framebuffer.h"
+#include "GPU_shader.h"
+#include "GPU_uniformbuffer.h"
+#include "GPU_viewport.h"
+#include "bmesh.h"
+
+#include "WM_types.h"
+#include "WM_api.h"
+
+
+
+#define LANPR_ENGINE "BLENDER_LANPR"
+
+#define TNS_PI 3.1415926535897932384626433832795
+#define deg(r) r / TNS_PI * 180.0
+#define rad(d) d *TNS_PI / 180.0
+
+#define tMatDist2v(p1, p2) \
+       sqrt(((p1)[0] - (p2)[0]) * ((p1)[0] - (p2)[0]) + ((p1)[1] - (p2)[1]) * ((p1)[1] - (p2)[1]))
+
+#define tnsLinearItp(L, R, T) \
+       ((L) * (1.0f - (T)) + (R)*(T))
+
+typedef struct LANPR_RenderBuffer LANPR_RenderBuffer;
+
+typedef struct LANPR_SharedResource {
+
+       /* We only allocate once for all */
+       LANPR_RenderBuffer *render_buffer_shared;
+
+       /* Snake */
+       GPUShader *multichannel_shader;
+       GPUShader *edge_detect_shader;
+       GPUShader *edge_thinning_shader;
+       GPUShader *snake_connection_shader;
+
+       /* DPIX */
+       GPUShader *dpix_transform_shader;
+       GPUShader *dpix_preview_shader;
+
+       /* Software */
+       GPUShader *software_shader;
+       GPUShader *software_chaining_shader;
+
+       void *ved_viewport;
+       void *ved_render;
+
+
+       int init_complete;
+
+       SpinLock render_flag_lock;
+       int during_render;        // get/set using access funcion which uses render_flag_lock to lock.
+                                 // this prevents duplicate too much resource. (no render preview in viewport while rendering)
+
+} LANPR_SharedResource;
+
+#define TNS_DPIX_TEXTURE_SIZE 2048
+
+typedef struct LANPR_TextureSample {
+       Link Item;
+       int X, Y;
+       float Z;    // for future usage
+} LANPR_TextureSample;
+
+typedef struct LANPR_LineStripPoint {
+       Link Item;
+       float P[3];
+} LANPR_LineStripPoint;
+
+typedef struct LANPR_LineStrip {
+       Link Item;
+       ListBase points;
+       int point_count;
+       float total_length;
+}LANPR_LineStrip;
+
+typedef struct LANPR_PassList {
+       /* Snake */
+       struct DRWPass *depth_pass;
+       struct DRWPass *color_pass;
+       struct DRWPass *normal_pass;
+       struct DRWPass *edge_intermediate;
+       struct DRWPass *edge_thinning;
+       struct DRWPass *snake_pass;
+
+       /* DPIX */
+       struct DRWPass *dpix_transform_pass;
+       struct DRWPass *dpix_preview_pass;
+
+       /* SOFTWARE */
+       struct DRWPass *software_pass;
+
+} LANPR_PassList;
+
+typedef struct LANPR_FramebufferList {
+
+       /* Snake */
+       struct GPUFrameBuffer *passes;
+       struct GPUFrameBuffer *edge_intermediate;
+       struct GPUFrameBuffer *edge_thinning;
+
+       /* DPIX */
+       struct GPUFrameBuffer *dpix_transform;
+       struct GPUFrameBuffer *dpix_preview;
+
+       /* Software */
+       struct GPUFrameBuffer *software_ms;
+
+} LANPR_FramebufferList;
+
+typedef struct LANPR_TextureList {
+
+       struct GPUTexture *color;
+       struct GPUTexture *normal;
+       struct GPUTexture *depth;
+       struct GPUTexture *edge_intermediate;
+
+       struct GPUTexture *dpix_in_pl;/* point L */
+       struct GPUTexture *dpix_in_pr;/* point R */
+       struct GPUTexture *dpix_in_nl;/* normal L */
+       struct GPUTexture *dpix_in_nr;/* normal R */
+       struct GPUTexture *dpix_in_edge_mask;/* RGBA, R:Material, G: Freestyle Edge Mark, BA:Reserved for future usage */
+
+       struct GPUTexture *dpix_out_pl;
+       struct GPUTexture *dpix_out_pr;
+       struct GPUTexture *dpix_out_length;
+
+       /* multisample resolve */
+       struct GPUTexture *ms_resolve_depth;
+       struct GPUTexture *ms_resolve_color;
+
+} LANPR_TextureList;
+
+typedef struct LANPR_PrivateData {
+       DRWShadingGroup *multipass_shgrp;
+       DRWShadingGroup *edge_detect_shgrp;
+       DRWShadingGroup *edge_thinning_shgrp;
+       DRWShadingGroup *snake_shgrp;
+
+       DRWShadingGroup *dpix_transform_shgrp;
+       DRWShadingGroup *dpix_preview_shgrp;
+
+       DRWShadingGroup *debug_shgrp;
+
+       //snake
+
+       float normal_clamp;
+       float normal_strength;
+       float depth_clamp;
+       float depth_strength;
+
+       float zfar;
+       float znear;
+
+       int stage;//thinning
+
+       float         *line_result;
+       unsigned char *line_result_8bit;
+       int width, height;          // if not match recreate buffer.
+       void         **sample_table;
+
+       BLI_mempool *mp_sample;
+       BLI_mempool *mp_line_strip;
+       BLI_mempool *mp_line_strip_point;
+       BLI_mempool *mp_batch_list;
+
+       ListBase pending_samples;
+       ListBase erased_samples;
+       ListBase line_strips;
+
+       // dpix data
+
+       void *atlas_pl;
+       void *atlas_pr;
+       void *atlas_nl;
+       void *atlas_nr;
+       void *atlas_edge_mask;
+
+       int begin_index;
+
+       int dpix_sample_step;
+       int dpix_is_perspective;
+       float dpix_viewport[4];
+       float output_viewport[4];
+       int dpix_buffer_width;
+       float dpix_depth_offset;
+
+       float dpix_znear;
+       float dpix_zfar;
+
+       // drawing
+
+       unsigned v_buf;
+       unsigned i_buf;
+       unsigned l_buf;
+
+       GPUVertFormat snake_gwn_format;
+       GPUBatch *snake_batch;
+
+       ListBase dpix_batch_list;
+
+} LANPR_PrivateData;
+
+typedef struct LANPR_StorageList {
+       LANPR_PrivateData *g_data;
+} LANPR_StorageList;
+
+typedef struct LANPR_BatchItem {
+       Link Item;
+       GPUBatch *dpix_transform_batch;
+       GPUBatch *dpix_preview_batch;
+       Object *ob;
+} LANPR_BatchItem;
+
+typedef struct LANPR_Data {
+       void *engine_type;
+       LANPR_FramebufferList *fbl;
+       LANPR_TextureList *txl;
+       LANPR_PassList *psl;
+       LANPR_StorageList *stl;
+} LANPR_Data;
+
+
+
+/* Below ported from NUL_TNS.h */
+
+#define TNS_THREAD_LINE_COUNT 10000
+
+#define TNS_CALCULATION_IDLE         0
+#define TNS_CALCULATION_GEOMETRY     1
+#define TNS_CALCULATION_CONTOUR      2
+#define TNS_CALCULATION_INTERSECTION 3
+#define TNS_CALCULATION_OCCLUTION    4
+#define TNS_CALCULATION_FINISHED     100
+
+typedef struct LANPR_RenderTaskInfo {
+       //thrd_t           ThreadHandle;
+
+       struct LANPR_RenderBuffer *RenderBuffer;
+       int ThreadID;
+
+       struct nListItemPointer *Contour;
+       ListBase ContourPointers;
+
+       struct nListItemPointer *Intersection;
+       ListBase IntersectionPointers;
+
+       struct nListItemPointer *Crease;
+       ListBase CreasePointers;
+
+       struct nListItemPointer *Material;
+       ListBase MaterialPointers;
+
+       struct nListItemPointer *EdgeMark;
+       ListBase EdgeMarkPointers;
+
+} LANPR_RenderTaskInfo;
+
+typedef struct LANPR_RenderBuffer {
+       struct LANPR_RenderBuffer *prev, *next;
+
+       //nSafeString*       Name;
+
+       //tnsFrameBuffer*    FrameBuffer;
+       //now we move frame buffer content here
+       int W, H;
+       int SubPixelSample;//1,2,3,4, Use Squared Value.
+       int TileSizeW, TileSizeH;
+       int TileCountX, TileCountY;
+       real WidthPerTile, HeightPerTile;
+       tnsMatrix44d ViewProjection;
+       tnsMatrix44d VPInverse;
+
+       nSafeString *OutputFolder;   //end with a slash;
+       nSafeString *ImagePrefix;
+       nSafeString *ImageNameConnector;
+
+       int OutputMode;
+       int OutputAALevel;
+
+       struct LANPR_BoundingArea *InitialBoundingAreas;
+       u32bit BoundingAreaCount;
+       //u32bit             BaVBO;
+       //u32bit           BaFillVBO;
+
+       ListBase VertexBufferPointers;
+       ListBase LineBufferPointers;
+       ListBase TriangleBufferPointers;
+       ListBase AllRenderLines;
+
+       ListBase IntersectingVertexBuffer;
+
+       struct GPUBatch *DPIXIntersectionTransformBatch;
+       struct GPUBatch *DPIXIntersectionBatch;
+
+       /* use own-implemented one */
+       nStaticMemoryPool RenderDataPool;
+
+       Material           *MaterialPointers[2048];
+
+       //render status
+
+       int cached_for_frame;
+
+       real ViewVector[3];
+
+       int TriangleSize;
+
+       u32bit ContourCount;
+       u32bit ContourProcessed;
+       nListItemPointer *ContourManaged;
+       ListBase Contours;
+
+       u32bit IntersectionCount;
+       u32bit IntersectionProcessed;
+       nListItemPointer *IntersectionManaged;
+       ListBase IntersectionLines;
+
+       u32bit CreaseCount;
+       u32bit CreaseProcessed;
+       nListItemPointer *CreaseManaged;
+       ListBase CreaseLines;
+
+       u32bit MaterialLineCount;
+       u32bit MaterialProcessed;
+       nListItemPointer *MaterialManaged;
+       ListBase MaterialLines;
+
+       u32bit EdgeMarkCount;
+       u32bit EdgeMarkProcessed;
+       nListItemPointer *EdgeMarkManaged;
+       ListBase EdgeMarks;
+
+       ListBase Chains;
+       GPUBatch *ChainDrawBatch;
+       DRWShadingGroup *ChainShgrp;
+
+       SpinLock csInfo;
+       SpinLock csData;
+       SpinLock csManagement;
+
+       //settings
+
+       //int             OutputTransparent;
+       //real            Backgroundcolor[4];
+
+       int MaxOccludeLevel;
+       real CreaseAngle;
+       real CreaseCos;
+       int CreaseAllowOverride;
+       int ThreadCount;
+
+       real OverallProgress;
+       int CalculationStatus;
+
+       int DrawMaterialPreview;
+       real MaterialTransparency;
+
+       int ShowLine;
+       int ShowFast;
+       int ShowMaterial;
+       int OverrideDisplay;
+
+       //nListHandle DrawCommands; /* not used now */
+
+       //tnsRenderBufferPreviewNode RenderPreview[32];
+
+       struct Scene *Scene;
+       struct Object *Camera;
+
+       int enable_intersections;
+       int size;
+
+       //tnsRenderTriangles are in mesh object.
+}LANPR_RenderBuffer;
+
+
+#define TNS_CULL_DISCARD 2
+#define TNS_CULL_USED    1
+
+typedef struct LANPR_RenderTriangle {
+       nListItem Item;
+       struct LANPR_RenderVert *V[3];
+       struct LANPR_RenderLine *RL[3];
+       real GN[3];
+       real GC[3];
+       //struct BMFace *F;
+       short MaterialID;
+       ListBase IntersectingVerts;
+       char CullStatus;
+       struct LANPR_RenderTriangle *Testing;   //Should Be tRT** Testing[NumOfThreads]
+}LANPR_RenderTriangle;
+
+typedef struct LANPR_RenderTriangleThread {
+       struct LANPR_RenderTriangle Base;
+       struct LANPR_RenderLine *Testing[127];    //max thread support;
+}LANPR_RenderTriangleThread;
+
+typedef struct LANPR_RenderElementLinkNode {
+       nListItem Item;
+       void *Pointer;
+       int ElementCount;
+       void *ObjectRef;
+       char Additional;
+}LANPR_RenderElementLinkNode;
+
+typedef struct LANPR_RenderLineSegment {
+       nListItem Item;
+       //real     Begin, End;  // 0->At[L] 1->At[R]
+       real at;
+       u8bit OcclusionLevel;    //after
+}LANPR_RenderLineSegment;
+
+typedef struct LANPR_RenderVert {
+       nListItem Item;
+       real GLocation[4];
+       real FrameBufferCoord[4];
+       int FrameBufferCoordi[2];
+       struct BMVert *V;              //Used As R When Intersecting
+       struct LANPR_RenderLine *IntersectingLine;
+       struct LANPR_RenderLine *IntersectintLine2;
+       struct LANPR_RenderTriangle *IntersectWith;     //   Positive 1         Negative 0
+       //tnsRenderTriangle* IntersectingOnFace;       //         <|               |>
+       char Positive;                    //                 L---->|----->R      L---->|----->R
+       char EdgeUsed;                    //                      <|                   |>
+}LANPR_RenderVert;
+
+#define LANPR_EDGE_FLAG_EDGE_MARK    1
+#define LANPR_EDGE_FLAG_CONTOUR      2
+#define LANPR_EDGE_FLAG_CREASE       4
+#define LANPR_EDGE_FLAG_MATERIAL     8
+#define LANPR_EDGE_FLAG_INTERSECTION 16
+#define LANPR_EDGE_FLAG_FLOATING     32 // floating edge, unimplemented yet
+#define LANPR_EDGE_FLAG_CHAIN_PICKED 64
+
+#define LANPR_EDGE_FLAG_ALL_TYPE     0x3f
+
+typedef struct LANPR_RenderLine {
+       nListItem Item;
+       struct LANPR_RenderVert *L, *R;
+       struct LANPR_RenderTriangle *TL, *TR;
+       ListBase Segments;
+       //tnsEdge*       Edge;//should be edge material
+       //tnsRenderTriangle* Testing;//Should Be tRT** Testing[NumOfThreads]
+       char MinOcclude;
+       char Flags; // also for line type determination on chainning
+       struct Object *ObjectRef;
+}LANPR_RenderLine;
+
+typedef struct LANPR_RenderLineChain {
+       nListItem Item;
+       ListBase Chain;
+       //int         SegmentCount;  // we count before draw cmd.
+       float Length;                // calculated before draw cmd.
+}LANPR_RenderLineChain;
+
+typedef struct LANPR_RenderLineChainItem {
+       nListItem Item;
+       float pos[3];       // need z value for fading
+       float normal[3];
+       char LineType;             //      style of [1]       style of [2]
+       char OcclusionLevel;         // [1]--------------->[2]---------------->[3]--....
+}LANPR_RenderLineChainItem;
+
+typedef struct LANPR_BoundingArea {
+       real L, R, U, B;
+       real CX, CY;
+
+       struct LANPR_BoundingArea *Child;//1,2,3,4 quadrant
+
+       ListBase LP;
+       ListBase RP;
+       ListBase UP;
+       ListBase BP;
+
+       int TriangleCount;
+       ListBase LinkedTriangles;
+       ListBase LinkedLines;
+       ListBase LinkedChains;//reserved for multithread chainning
+}LANPR_BoundingArea;
+
+
+#define TNS_COMMAND_LINE     0
+#define TNS_COMMAND_MATERIAL 1
+#define TNS_COMMAND_EDGE     2
+
+#define TNS_TRANSPARENCY_DRAW_SIMPLE  0
+#define TNS_TRANSPARENCY_DRAW_LAYERED 1
+
+#define TNS_OVERRIDE_ONLY                     0
+#define TNS_OVERRIDE_EXCLUDE                  1
+//#define TNS_OVERRIDE_ALL_OTHERS_OUTSIDE_GROUP 2
+//#define TNS_OVERRIDE_ALL_OTHERS_IN_GROUP      3
+//#define TNS_OVERRIDE_ALL_OTHERS               4
+
+extern RenderEngineType DRW_engine_viewport_lanpr_type;
+
+
+
+#define tnsLinearItp(L, R, T) \
+       ((L) * (1.0f - (T)) + (R)*(T))
+
+
+#define TNS_TILE(tile, r, c, CCount) \
+       tile[r * CCount + c]
+
+#define TNS_CLAMP(a, Min, Max) \
+       a = a < Min ? Min : (a > Max ? Max : a)
+
+#define TNS_MAX2_INDEX(a, b) \
+       (a > b ? 0 : 1)
+
+#define TNS_MIN2_INDEX(a, b) \
+       (a < b ? 0 : 1)
+
+#define TNS_MAX3_INDEX(a, b, c) \
+       (a > b ? (a > c ? 0 : (b > c ? 1 : 2)) : (b > c ? 1 : 2))
+
+#define TNS_MIN3_INDEX(a, b, c) \
+       (a < b ? (a < c ? 0 : (b < c ? 1 : 2)) : (b < c ? 1 : 2))
+
+#define TNS_MAX3_INDEX_ABC(x, y, z) \
+       (x > y ? (x > z ? a : (y > z ? b : c)) : (y > z ? b : c))
+
+#define TNS_MIN3_INDEX_ABC(x, y, z) \
+       (x < y ? (x < z ? a : (y < z ? b : c)) : (y < z ? b : c))
+
+#define TNS_ABC(index) \
+       (index == 0 ? a : (index == 1 ? b : c))
+
+
+#define TNS_DOUBLE_CLOSE_ENOUGH(a, b) \
+       (((a) + DBL_EDGE_LIM) >= (b) && ((a) - DBL_EDGE_LIM) <= (b))
+
+//#define TNS_DOUBLE_CLOSE_ENOUGH(a,b)\
+// //(((a)+0.00000000001)>=(b) && ((a)-0.0000000001)<=(b))
+
+
+#define TNS_FLOAT_CLOSE_ENOUGH_WIDER(a, b) \
+       (((a) + 0.0000001) >= (b) && ((a) - 0.0000001) <= (b))
+
+#define TNS_IN_TILE_X(RenderTile, Fx) \
+       (RenderTile->FX <= Fx && RenderTile->FXLim >= Fx)
+
+#define TNS_IN_TILE_Y(RenderTile, Fy) \
+       (RenderTile->FY <= Fy && RenderTile->FYLim >= Fy)
+
+
+#define TNS_IN_TILE(RenderTile, Fx, Fy) \
+       (TNS_IN_TILE_X(RenderTile, Fx) && TNS_IN_TILE_Y(RenderTile, Fy))
+
+BLI_INLINE void tMatConvert44df(tnsMatrix44d from, tnsMatrix44f to) {
+       to[0] = from[0];
+       to[1] = from[1];
+       to[2] = from[2];
+       to[3] = from[3];
+       to[4] = from[4];
+       to[5] = from[5];
+       to[6] = from[6];
+       to[7] = from[7];
+       to[8] = from[8];
+       to[9] = from[9];
+       to[10] = from[10];
+       to[11] = from[11];
+       to[12] = from[12];
+       to[13] = from[13];
+       to[14] = from[14];
+       to[15] = from[15];
+}
+
+BLI_INLINE int lanpr_TrangleLineBoundBoxTest(LANPR_RenderTriangle *rt, LANPR_RenderLine *rl) {
+       if (MAX3(rt->V[0]->FrameBufferCoord[2], rt->V[1]->FrameBufferCoord[2], rt->V[2]->FrameBufferCoord[2]) > MIN2(rl->L->FrameBufferCoord[2], rl->R->FrameBufferCoord[2])) return 0;
+       if (MAX3(rt->V[0]->FrameBufferCoord[0], rt->V[1]->FrameBufferCoord[0], rt->V[2]->FrameBufferCoord[0]) < MIN2(rl->L->FrameBufferCoord[0], rl->R->FrameBufferCoord[0])) return 0;
+       if (MIN3(rt->V[0]->FrameBufferCoord[0], rt->V[1]->FrameBufferCoord[0], rt->V[2]->FrameBufferCoord[0]) > MAX2(rl->L->FrameBufferCoord[0], rl->R->FrameBufferCoord[0])) return 0;
+       if (MAX3(rt->V[0]->FrameBufferCoord[1], rt->V[1]->FrameBufferCoord[1], rt->V[2]->FrameBufferCoord[1]) < MIN2(rl->L->FrameBufferCoord[1], rl->R->FrameBufferCoord[1])) return 0;
+       if (MIN3(rt->V[0]->FrameBufferCoord[1], rt->V[1]->FrameBufferCoord[1], rt->V[2]->FrameBufferCoord[1]) > MAX2(rl->L->FrameBufferCoord[1], rl->R->FrameBufferCoord[1])) return 0;
+       return 1;
+}
+
+BLI_INLINE double tMatGetLinearRatio(real L, real R, real FromL);
+BLI_INLINE int lanpr_LineIntersectTest2d(const double *a1, const double *a2, const double *b1, const double *b2, double *aRatio) {
+       double k1, k2;
+       double x;
+       double y;
+       double Ratio;
+       double xDiff = (a2[0] - a1[0]);// +DBL_EPSILON;
+       double xDiff2 = (b2[0] - b1[0]);
+
+       if (xDiff == 0) {
+               if (xDiff2 == 0) {
+                       *aRatio = 0;
+                       return 0;
+               }
+               double r2 = tMatGetLinearRatio(b1[0], b2[0], a1[0]);
+               x = tnsLinearItp(b1[0], b2[0], r2);
+               y = tnsLinearItp(b1[1], b2[1], r2);
+               *aRatio = Ratio = tMatGetLinearRatio(a1[1], a2[1], y);
+       }
+       else {
+               if (xDiff2 == 0) {
+                       Ratio = tMatGetLinearRatio(a1[0], a2[0], b1[0]);
+                       x = tnsLinearItp(a1[0], a2[0], Ratio);
+                       *aRatio = Ratio;
+               }
+               else {
+                       k1 = (a2[1] - a1[1]) / xDiff;
+                       k2 = (b2[1] - b1[1]) / xDiff2;
+
+                       if ((k1 == k2))
+                               return 0;
+
+                       x = (a1[1] - b1[1] - k1 * a1[0] + k2 * b1[0]) / (k2 - k1);
+
+                       Ratio = (x - a1[0]) / xDiff;
+
+                       *aRatio = Ratio;
+               }
+       }
+
+
+
+       if (b1[0] == b2[0]) {
+               y = tnsLinearItp(a1[1], a2[1], Ratio);
+               if (y > MAX2(b1[1], b2[1]) || y < MIN2(b1[1], b2[1])) return 0;
+       }
+       else
+       if (Ratio <= 0 || Ratio > 1 ||
+           (b1[0] > b2[0] && x > b1[0]) ||
+           (b1[0] < b2[0] && x < b1[0]) ||
+           (b2[0] > b1[0] && x > b2[0]) ||
+           (b2[0] < b1[0] && x < b2[0]))
+               return 0;
+
+       return 1;
+}
+BLI_INLINE double lanpr_GetLineZ(tnsVector3d L, tnsVector3d R, real Ratio) {
+       //double z = 1 / tnsLinearItp(1 / L[2], 1 / R[2], Ratio);
+       double z = tnsLinearItp(L[2], R[2], Ratio);
+       return z;
+}
+BLI_INLINE double lanpr_GetLineZPoint(tnsVector3d L, tnsVector3d R, tnsVector3d FromL) {
+       double r = (FromL[0] - L[0]) / (R[0] - L[0]);
+       return tnsLinearItp(L[2], R[2], r);
+       //return 1 / tnsLinearItp(1 / L[2], 1 / R[2], r);
+}
+BLI_INLINE double lanpr_GetLinearRatio(tnsVector3d L, tnsVector3d R, tnsVector3d FromL) {
+       double r = (FromL[0] - L[0]) / (R[0] - L[0]);
+       return r;
+}
+
+BLI_INLINE double tMatGetLinearRatio(real L, real R, real FromL) {
+       double r = (FromL - L) / (R - L);
+       return r;
+}
+BLI_INLINE void tMatVectorMinus2d(tnsVector2d result, tnsVector2d l, tnsVector2d r) {
+       result[0] = l[0] - r[0];
+       result[1] = l[1] - r[1];
+}
+
+BLI_INLINE void tMatVectorMinus3d(tnsVector3d result, tnsVector3d l, tnsVector3d r) {
+       result[0] = l[0] - r[0];
+       result[1] = l[1] - r[1];
+       result[2] = l[2] - r[2];
+}
+BLI_INLINE void tMatVectorSubtract3d(tnsVector3d l, tnsVector3d r) {
+       l[0] = l[0] - r[0];
+       l[1] = l[1] - r[1];
+       l[2] = l[2] - r[2];
+}
+BLI_INLINE void tMatVectorPlus3d(tnsVector3d result, tnsVector3d l, tnsVector3d r) {
+       result[0] = l[0] + r[0];
+       result[1] = l[1] + r[1];
+       result[2] = l[2] + r[2];
+}
+BLI_INLINE void tMatVectorAccum3d(tnsVector3d l, tnsVector3d r) {
+       l[0] = l[0] + r[0];
+       l[1] = l[1] + r[1];
+       l[2] = l[2] + r[2];
+}
+BLI_INLINE void tMatVectorAccum2d(tnsVector2d l, tnsVector2d r) {
+       l[0] = l[0] + r[0];
+       l[1] = l[1] + r[1];
+}
+BLI_INLINE void tMatVectorNegate3d(tnsVector3d result, tnsVector3d l) {
+       result[0] = -l[0];
+       result[1] = -l[1];
+       result[2] = -l[2];
+}
+BLI_INLINE void tMatVectorNegateSelf3d(tnsVector3d l) {
+       l[0] = -l[0];
+       l[1] = -l[1];
+       l[2] = -l[2];
+}
+BLI_INLINE void tMatVectorCopy2d(tnsVector2d from, tnsVector2d to) {
+       to[0] = from[0];
+       to[1] = from[1];
+}
+BLI_INLINE void tMatVectorCopy3d(tnsVector3d from, tnsVector3d to) {
+       to[0] = from[0];
+       to[1] = from[1];
+       to[2] = from[2];
+}
+BLI_INLINE void tMatVectorCopy4d(tnsVector4d from, tnsVector4d to) {
+       to[0] = from[0];
+       to[1] = from[1];
+       to[2] = from[2];
+       to[3] = from[3];
+}
+BLI_INLINE void tMatVectorMultiSelf4d(tnsVector3d from, real num) {
+       from[0] *= num;
+       from[1] *= num;
+       from[2] *= num;
+       from[3] *= num;
+}
+BLI_INLINE void tMatVectorMultiSelf3d(tnsVector3d from, real num) {
+       from[0] *= num;
+       from[1] *= num;
+       from[2] *= num;
+}
+BLI_INLINE void tMatVectorMultiSelf2d(tnsVector3d from, real num) {
+       from[0] *= num;
+       from[1] *= num;
+}
+
+BLI_INLINE real tMatDirectionToRad(tnsVector2d Dir) {
+       real arcc = acos(Dir[0]);
+       real arcs = asin(Dir[1]);
+
+       if (Dir[0] >= 0) {
+               if (Dir[1] >= 0) return arcc;
+               else return TNS_PI * 2 - arcc;
+       }
+       else {
+               if (Dir[1] >= 0) return arcs + TNS_PI / 2;
+               else return TNS_PI + arcs;
+       }
+}
+
+
+BLI_INLINE void tMatVectorConvert4fd(tnsVector4f from, tnsVector4d to) {
+       to[0] = from[0];
+       to[1] = from[1];
+       to[2] = from[2];
+       to[3] = from[3];
+}
+
+BLI_INLINE void tMatVectorConvert3fd(tnsVector3f from, tnsVector3d to) {
+       to[0] = from[0];
+       to[1] = from[1];
+       to[2] = from[2];
+}
+
+
+int lanpr_point_inside_triangled(tnsVector2d v, tnsVector2d v0, tnsVector2d v1, tnsVector2d v2);
+real lanpr_LinearInterpolate(real L, real R, real T);
+void lanpr_LinearInterpolate2dv(real *L, real *R, real T, real *Result);
+void lanpr_LinearInterpolate3dv(real *L, real *R, real T, real *Result);
+
+
+
+// functions
+
+// dpix
+
+void lanpr_init_atlas_inputs(void *ved);
+void lanpr_destroy_atlas(void *ved);
+int lanpr_feed_atlas_data_obj(void *vedata,
+                              float *AtlasPointsL, float *AtlasPointsR,
+                              float *AtlasFaceNormalL, float *AtlasFaceNormalR,
+                              float *AtlasEdgeMask,
+                              Object *ob, int begin_index);
+
+int lanpr_feed_atlas_data_intersection_cache(void *vedata,
+                                             float *AtlasPointsL, float *AtlasPointsR,
+                                             float *AtlasFaceNormalL, float *AtlasFaceNormalR,
+                                             float *AtlasEdgeMask,
+                                             int begin_index);
+
+int lanpr_feed_atlas_trigger_preview_obj(void *vedata, Object *ob, int begin_index);
+void lanpr_create_atlas_intersection_preview(void *vedata, int begin_index);
+
+void lanpr_dpix_draw_scene(LANPR_TextureList *txl, LANPR_FramebufferList *fbl, LANPR_PassList *psl, LANPR_PrivateData *pd, SceneLANPR *lanpr, GPUFrameBuffer *DefaultFB, int is_render);
+
+void lanpr_snake_draw_scene(LANPR_TextureList *txl, LANPR_FramebufferList *fbl, LANPR_PassList *psl, LANPR_PrivateData *pd, SceneLANPR *lanpr, GPUFrameBuffer *DefaultFB, int is_render);
+
+void lanpr_software_draw_scene(void *vedata, GPUFrameBuffer *dfb, int is_render);
+
+void lanpr_set_render_flag();
+void lanpr_clear_render_flag();
+int lanpr_during_render();
+
diff --git a/source/blender/draw/engines/lanpr/lanpr_chain.c b/source/blender/draw/engines/lanpr/lanpr_chain.c
new file mode 100644 (file)
index 0000000..f1bdaee
--- /dev/null
@@ -0,0 +1,421 @@
+#include "DRW_engine.h"
+#include "DRW_render.h"
+#include "BLI_listbase.h"
+#include "BLI_linklist.h"
+#include "BLI_math.h"
+#include "lanpr_all.h"
+#include "DRW_render.h"
+#include "BKE_object.h"
+#include "DNA_mesh_types.h"
+#include "DNA_camera_types.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_framebuffer.h"
+#include "DNA_lanpr_types.h"
+#include "DNA_meshdata_types.h"
+#include "BKE_customdata.h"
+#include "DEG_depsgraph_query.h"
+#include "GPU_draw.h"
+
+#include "GPU_batch.h"
+#include "GPU_framebuffer.h"
+#include "GPU_shader.h"
+#include "GPU_uniformbuffer.h"
+#include "GPU_viewport.h"
+#include "bmesh.h"
+
+#include <math.h>
+
+int lanpr_get_line_bounding_areas(LANPR_RenderBuffer *rb, LANPR_RenderLine *rl, int *rowBegin, int *rowEnd, int *colBegin, int *colEnd);
+LANPR_BoundingArea *lanpr_get_point_bounding_area(LANPR_RenderBuffer *rb, real x, real y);
+
+#define LANPR_OTHER_RV(rl, rv) ((rv) == (rl)->L ? (rl)->R : (rl)->L)
+
+LANPR_RenderLine *lanpr_get_connected_render_line(LANPR_BoundingArea *ba, LANPR_RenderVert *rv, LANPR_RenderVert **new_rv) {
+       nListItemPointer *lip;
+       LANPR_RenderLine *nrl;
+       real cosine;
+
+       for (lip = ba->LinkedLines.first; lip; lip = lip->pNext) {
+               nrl = lip->p;
+
+               if ((!(nrl->Flags & LANPR_EDGE_FLAG_ALL_TYPE)) || (nrl->Flags & LANPR_EDGE_FLAG_CHAIN_PICKED)) continue;
+
+               // always chain connected lines for now.
+               // simplification will take care of the sharp points.
+               // if(cosine whatever) continue;
+
+               if (rv != nrl->L && rv != nrl->R) {
+                       if (nrl->Flags & LANPR_EDGE_FLAG_INTERSECTION) {
+                               if (rv->FrameBufferCoord[0] == nrl->L->FrameBufferCoord[0] && rv->FrameBufferCoord[1] == nrl->L->FrameBufferCoord[1]) {
+                                       *new_rv = LANPR_OTHER_RV(nrl, nrl->L);
+                                       return nrl;
+                               } elif(rv->FrameBufferCoord[0] == nrl->R->FrameBufferCoord[0] && rv->FrameBufferCoord[1] == nrl->R->FrameBufferCoord[1])
+                               {
+                                       *new_rv = LANPR_OTHER_RV(nrl, nrl->R);
+                                       return nrl;
+                               }
+                       }
+                       continue;
+               }
+
+               *new_rv = LANPR_OTHER_RV(nrl, rv);
+               return nrl;
+       }
+
+       return 0;
+}
+
+int lanpr_get_nearby_render_line(LANPR_BoundingArea *ba, LANPR_RenderLine *rl){
+       // hold on
+       return 1;
+}
+
+LANPR_RenderLineChain *lanpr_create_render_line_chain(LANPR_RenderBuffer *rb){
+       LANPR_RenderLineChain *rlc;
+       rlc = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLineChain));
+
+       BLI_addtail(&rb->Chains, rlc);
+
+       return rlc;
+}
+
+LANPR_RenderLineChainItem *lanpr_append_render_line_chain_point(LANPR_RenderBuffer *rb, LANPR_RenderLineChain *rlc, float x, float y, float* normal, char type, int level){
+       LANPR_RenderLineChainItem *rlci;
+       rlci = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLineChainItem));
+
+       rlci->pos[0] = x;
+       rlci->pos[1] = y;
+       copy_v3_v3(rlci->normal, normal);
+       rlci->LineType = type & LANPR_EDGE_FLAG_ALL_TYPE;
+       rlci->OcclusionLevel = level;
+       BLI_addtail(&rlc->Chain, rlci);
+
+       //printf("a %f,%f %d\n", x, y, level);
+
+       return rlci;
+}
+
+LANPR_RenderLineChainItem *lanpr_push_render_line_chain_point(LANPR_RenderBuffer *rb, LANPR_RenderLineChain *rlc, float x, float y, float* normal, char type, int level){
+       LANPR_RenderLineChainItem *rlci;
+       rlci = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLineChainItem));
+
+       rlci->pos[0] = x;
+       rlci->pos[1] = y;
+       copy_v3_v3(rlci->normal, normal);
+       rlci->LineType = type & LANPR_EDGE_FLAG_ALL_TYPE;
+       rlci->OcclusionLevel = level;
+       BLI_addhead(&rlc->Chain, rlci);
+
+       //printf("p %f,%f %d\n", x, y, level);
+
+       return rlci;
+}
+
+// refer to http://karthaus.nl/rdp/ for description
+void lanpr_reduce_render_line_chain_recursive(LANPR_RenderLineChain *rlc, LANPR_RenderLineChainItem *from, LANPR_RenderLineChainItem *to, float dist_threshold){
+       LANPR_RenderLineChainItem *rlci, *next_rlci;
+       float l[2], r[2], c[2];
+       float max_dist = 0;
+       LANPR_RenderLineChainItem *max_rlci = 0;
+
+       // find the max distance item
+       for (rlci = from->Item.pNext; rlci != to; rlci = next_rlci) {
+               next_rlci = rlci->Item.pNext;
+
+               if (next_rlci && (next_rlci->OcclusionLevel != rlci->OcclusionLevel || next_rlci->LineType != rlci->LineType)) continue;
+
+               float dist = dist_to_line_segment_v2(rlci->pos, from->pos, to->pos);
+               if (dist > dist_threshold && dist > max_dist) { max_dist = dist; max_rlci = rlci; }
+               //if (dist <= dist_threshold) BLI_remlink(&rlc->Chain, (void*)rlci);
+       }
+
+       if (!max_rlci) {
+               if (from->Item.pNext == to) return;
+               for (rlci = from->Item.pNext; rlci != to; rlci = next_rlci) {
+                       next_rlci = rlci->Item.pNext;
+                       if (next_rlci && (next_rlci->OcclusionLevel != rlci->OcclusionLevel || next_rlci->LineType != rlci->LineType)) continue;
+                       BLI_remlink(&rlc->Chain, (void *)rlci);
+               }
+       }
+       else {
+               if (from->Item.pNext != max_rlci) lanpr_reduce_render_line_chain_recursive(rlc, from, max_rlci, dist_threshold);
+               if (to->Item.pPrev != max_rlci) lanpr_reduce_render_line_chain_recursive(rlc, max_rlci, to, dist_threshold);
+       }
+}
+
+
+void lanpr_NO_THREAD_chain_feature_lines(LANPR_RenderBuffer *rb, float dist_threshold){
+       LANPR_RenderLineChain *rlc;
+       LANPR_RenderLineChainItem *rlci;
+       LANPR_RenderLine *rl;
+       LANPR_BoundingArea *ba;
+       LANPR_RenderLineSegment *rls;
+
+       for (rl = rb->AllRenderLines.first; rl; rl = rl->Item.pNext) {
+
+               if ((!(rl->Flags & LANPR_EDGE_FLAG_ALL_TYPE)) || (rl->Flags & LANPR_EDGE_FLAG_CHAIN_PICKED)) continue;
+
+               rl->Flags |= LANPR_EDGE_FLAG_CHAIN_PICKED;
+
+               rlc = lanpr_create_render_line_chain(rb);
+
+               int r1, r2, c1, c2, row, col;
+               LANPR_RenderLine *new_rl = rl;
+               LANPR_RenderVert *new_rv;
+               float N[3] = { 0 };
+
+               if (rl->TL) {
+                       N[0] += rl->TL->GN[0];
+                       N[1] += rl->TL->GN[1];
+                       N[2] += rl->TL->GN[2];
+               }
+               if (rl->TR) {
+                       N[0] += rl->TR->GN[0];
+                       N[1] += rl->TR->GN[1];
+                       N[2] += rl->TR->GN[2];
+               }
+               if (rl->TL || rl->TR) {
+                       normalize_v3(N);
+               }
+
+               // step 1: grow left
+               ba = lanpr_get_point_bounding_area(rb, rl->L->FrameBufferCoord[0], rl->L->FrameBufferCoord[1]);
+               new_rv = rl->L;
+               rls = rl->Segments.first;
+               lanpr_push_render_line_chain_point(rb, rlc, new_rv->FrameBufferCoord[0], new_rv->FrameBufferCoord[1], N, rl->Flags, rls->OcclusionLevel);
+               while (ba && (new_rl = lanpr_get_connected_render_line(ba, new_rv, &new_rv))) {
+                       new_rl->Flags |= LANPR_EDGE_FLAG_CHAIN_PICKED;
+
+                       int last_occlusion;
+
+                       N[0] = N[1] = N[2] = 0;
+                       if (new_rl->TL) {
+                               N[0] += new_rl ->TL->GN[0];
+                               N[1] += new_rl ->TL->GN[1];
+                               N[2] += new_rl ->TL->GN[2];
+                       }
+                       if (new_rl->TR) {
+                               N[0] += new_rl->TR->GN[0];
+                               N[1] += new_rl->TR->GN[1];
+                               N[2] += new_rl->TR->GN[2];
+                       }
+                       if (rl->TL || rl->TR) {
+                               normalize_v3(N);
+                       }
+
+                       if (new_rv == new_rl->L) {
+                               for (rls = new_rl->Segments.last; rls; rls = rls->Item.pPrev) {
+                                       float px, py;
+                                       px = tnsLinearItp(new_rl->L->FrameBufferCoord[0], new_rl->R->FrameBufferCoord[0], rls->at);
+                                       py = tnsLinearItp(new_rl->L->FrameBufferCoord[1], new_rl->R->FrameBufferCoord[1], rls->at);
+                                       lanpr_push_render_line_chain_point(rb, rlc, px, py, N, new_rl->Flags, rls->OcclusionLevel);
+                               }
+                       } elif(new_rv == new_rl->R)
+                       {
+                               rls = new_rl->Segments.first;
+                               last_occlusion = rls->OcclusionLevel;
+                               rls = rls->Item.pNext;
+                               for (rls; rls; rls = rls->Item.pNext) {
+                                       float px, py;
+                                       px = tnsLinearItp(new_rl->L->FrameBufferCoord[0], new_rl->R->FrameBufferCoord[0], rls->at);
+                                       py = tnsLinearItp(new_rl->L->FrameBufferCoord[1], new_rl->R->FrameBufferCoord[1], rls->at);
+                                       lanpr_push_render_line_chain_point(rb, rlc, px, py, N, new_rl->Flags, last_occlusion);
+                                       last_occlusion = rls->OcclusionLevel;
+                               }
+                               lanpr_push_render_line_chain_point(rb, rlc, new_rl->R->FrameBufferCoord[0], new_rl->R->FrameBufferCoord[1], N, new_rl->Flags, last_occlusion);
+                       }
+                       ba = lanpr_get_point_bounding_area(rb, new_rv->FrameBufferCoord[0], new_rv->FrameBufferCoord[1]);
+               }
+
+               // step 2: this line
+               rls = rl->Segments.first;
+               for (rls = rls->Item.pNext; rls; rls = rls->Item.pNext) {
+                       float px, py;
+                       px = tnsLinearItp(rl->L->FrameBufferCoord[0], rl->R->FrameBufferCoord[0], rls->at);
+                       py = tnsLinearItp(rl->L->FrameBufferCoord[1], rl->R->FrameBufferCoord[1], rls->at);
+                       lanpr_append_render_line_chain_point(rb, rlc, px, py, N, rl->Flags, rls->OcclusionLevel);
+               }
+               lanpr_append_render_line_chain_point(rb, rlc, rl->R->FrameBufferCoord[0], rl->R->FrameBufferCoord[1], N, rl->Flags, 0);
+
+               // step 3: grow right
+               ba = lanpr_get_point_bounding_area(rb, rl->R->FrameBufferCoord[0], rl->R->FrameBufferCoord[1]);
+               new_rv = rl->R;
+               // below already done in step 2
+               // lanpr_push_render_line_chain_point(rb,rlc,new_rv->FrameBufferCoord[0],new_rv->FrameBufferCoord[1],rl->Flags,0);
+               while (ba && (new_rl = lanpr_get_connected_render_line(ba, new_rv, &new_rv))) {
+                       new_rl->Flags |= LANPR_EDGE_FLAG_CHAIN_PICKED;
+
+                       int last_occlusion;
+
+                       // fix leading vertex type
+                       rlci = rlc->Chain.last;
+                       rlci->LineType = new_rl->Flags & LANPR_EDGE_FLAG_ALL_TYPE;
+
+                       if (new_rv == new_rl->L) {
+                               rls = new_rl->Segments.last;
+                               last_occlusion = rls->OcclusionLevel;
+                               rlci->OcclusionLevel = last_occlusion;
+                               rls = rls->Item.pPrev;
+                               if (rls) last_occlusion = rls->OcclusionLevel;
+                               for (rls = new_rl->Segments.last; rls; rls = rls->Item.pPrev) {
+                                       float px, py;
+                                       px = tnsLinearItp(new_rl->L->FrameBufferCoord[0], new_rl->R->FrameBufferCoord[0], rls->at);
+                                       py = tnsLinearItp(new_rl->L->FrameBufferCoord[1], new_rl->R->FrameBufferCoord[1], rls->at);
+                                       last_occlusion = rls->Item.pPrev ? ((LANPR_RenderLineSegment *)rls->Item.pPrev)->OcclusionLevel : 0;
+                                       lanpr_append_render_line_chain_point(rb, rlc, px, py, N, new_rl->Flags, last_occlusion);
+                               }
+                       } elif(new_rv == new_rl->R)
+                       {
+                               rls = new_rl->Segments.first;
+                               last_occlusion = rls->OcclusionLevel;
+                               rlci->OcclusionLevel = last_occlusion;
+                               rls = rls->Item.pNext;
+                               for (rls; rls; rls = rls->Item.pNext) {
+                                       float px, py;
+                                       px = tnsLinearItp(new_rl->L->FrameBufferCoord[0], new_rl->R->FrameBufferCoord[0], rls->at);
+                                       py = tnsLinearItp(new_rl->L->FrameBufferCoord[1], new_rl->R->FrameBufferCoord[1], rls->at);
+                                       lanpr_append_render_line_chain_point(rb, rlc, px, py, N, new_rl->Flags, rls->OcclusionLevel);
+                                       //last_occlusion = rls->OcclusionLevel;
+                               }
+                               lanpr_append_render_line_chain_point(rb, rlc, new_rl->R->FrameBufferCoord[0], new_rl->R->FrameBufferCoord[1], N, new_rl->Flags, 0);
+                       }
+                       ba = lanpr_get_point_bounding_area(rb, new_rv->FrameBufferCoord[0], new_rv->FrameBufferCoord[1]);
+               }
+
+               //LANPR_RenderLineChainItem* rlci;
+               //printf("line:\n");
+               //for (rlci = rlc->Chain.first; rlci; rlci = rlci->Item.pNext) {
+               //      printf("  %f,%f %d\n", rlci->pos[0],rlci->pos[1], rlci->OcclusionLevel);
+               //}
+               //printf("--------\n");
+
+               //lanpr_reduce_render_line_chain_recursive(rlc,rlc->Chain.first, rlc->Chain.last, dist_threshold);
+       }
+}
+
+int lanpr_count_chain(LANPR_RenderLineChain *rlc){
+       LANPR_RenderLineChainItem *rlci;
+       int Count = 0;
+       for (rlci = rlc->Chain.first; rlci; rlci = rlci->Item.pNext) {
+               Count++;
+       }
+       return Count;
+}
+
+float lanpr_compute_chain_length(LANPR_RenderLineChain *rlc, float *lengths, int begin_index) {
+       LANPR_RenderLineChainItem *rlci;
+       int i = 0;
+       float offset_accum = 0;
+       float dist;
+       float last_point[2];
+
+       rlci = rlc->Chain.first;
+       copy_v2_v2(last_point, rlci->pos);
+       for (rlci = rlc->Chain.first; rlci; rlci = rlci->Item.pNext) {
+               dist = len_v2v2(rlci->pos, last_point);
+               offset_accum += dist;
+               lengths[begin_index + i] = offset_accum;
+               copy_v2_v2(last_point, rlci->pos);
+               i++;
+       }
+       return offset_accum;
+}
+
+int lanpr_get_gpu_line_type(LANPR_RenderLineChainItem *rlci) {
+       switch (rlci->LineType) {
+               case LANPR_EDGE_FLAG_CONTOUR:         return 0;
+               case LANPR_EDGE_FLAG_CREASE:          return 1;
+               case LANPR_EDGE_FLAG_MATERIAL:        return 2;
+               case LANPR_EDGE_FLAG_EDGE_MARK:       return 3;
+               case LANPR_EDGE_FLAG_INTERSECTION:    return 4;
+               default: return 0;
+       }
+}
+
+void lanpr_chain_generate_draw_command(LANPR_RenderBuffer *rb){
+       LANPR_RenderLineChain *rlc;
+       LANPR_RenderLineChainItem *rlci;
+       int vert_count = 0;
+       int i = 0;
+       int arg;
+       float total_length;
+       float *lengths;
+       float length_target[2];
+
+       static GPUVertFormat format = { 0 };
+       static struct { uint pos, uvs, normal, type, level; } attr_id;
+       if (format.attr_len == 0) {
+               attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+               attr_id.uvs = GPU_vertformat_attr_add(&format, "uvs", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+               attr_id.normal = GPU_vertformat_attr_add(&format, "normal", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+               attr_id.type = GPU_vertformat_attr_add(&format, "type", GPU_COMP_I32, 1, GPU_FETCH_INT);
+               attr_id.level = GPU_vertformat_attr_add(&format, "level", GPU_COMP_I32, 1, GPU_FETCH_INT);
+       }
+
+       GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+
+       for (rlc = rb->Chains.first; rlc; rlc = rlc->Item.pNext) {
+               int count = lanpr_count_chain(rlc);
+               //printf("seg contains %d verts\n", count);
+               vert_count += count;
+       }
+
+       GPU_vertbuf_data_alloc(vbo, vert_count + 1); // serve as end point's adj.
+
+       lengths = MEM_callocN(sizeof(float) * vert_count, "chain lengths");
+
+       GPUIndexBufBuilder elb;
+       GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINES_ADJ, vert_count * 4, vert_count, true);// elem count will not exceed vert_count
+
+       for (rlc = rb->Chains.first; rlc; rlc = rlc->Item.pNext) {
+
+               total_length = lanpr_compute_chain_length(rlc, lengths, i);
+
+               for (rlci = rlc->Chain.first; rlci; rlci = rlci->Item.pNext) {
+
+                       length_target[0] = lengths[i];
+                       length_target[1] = total_length - lengths[i];
+
+                       GPU_vertbuf_attr_set(vbo, attr_id.pos, i, rlci->pos);
+                       GPU_vertbuf_attr_set(vbo, attr_id.normal, i, rlci->normal);
+                       GPU_vertbuf_attr_set(vbo, attr_id.uvs, i, length_target);
+
+                       arg = lanpr_get_gpu_line_type(rlci);
+                       GPU_vertbuf_attr_set(vbo, attr_id.type, i, &arg);
+
+                       arg = (int)rlci->OcclusionLevel;
+                       GPU_vertbuf_attr_set(vbo, attr_id.level, i, &arg);
+
+                       if (rlci == rlc->Chain.last) {
+                               if (rlci->Item.pPrev == rlc->Chain.first) {
+                                       length_target[1] = total_length;
+                                       GPU_vertbuf_attr_set(vbo, attr_id.uvs, i, length_target);
+                               }
+                               i++;
+                               continue;
+                       }
+
+                       if (rlci == rlc->Chain.first) {
+                               if (rlci->Item.pNext == rlc->Chain.last) GPU_indexbuf_add_line_adj_verts(&elb, vert_count, i, i + 1, vert_count);
+                               else GPU_indexbuf_add_line_adj_verts(&elb, vert_count, i, i + 1, i + 2);
+                       }
+                       else {
+                               if (rlci->Item.pNext == rlc->Chain.last) GPU_indexbuf_add_line_adj_verts(&elb, i - 1, i, i + 1, vert_count);
+                               else GPU_indexbuf_add_line_adj_verts(&elb, i - 1, i, i + 1, i + 2);
+                       }
+
+                       i++;
+               }
+       }
+       //set end point flag value.
+       length_target[0] = 3e30f;
+       length_target[1] = 3e30f;
+       GPU_vertbuf_attr_set(vbo, attr_id.pos, vert_count, length_target);
+
+       MEM_freeN(lengths);
+
+       if (rb->ChainDrawBatch) GPU_batch_discard(rb->ChainDrawBatch);
+       rb->ChainDrawBatch = GPU_batch_create_ex(GPU_PRIM_LINES_ADJ, vbo, GPU_indexbuf_build(&elb), GPU_USAGE_DYNAMIC | GPU_BATCH_OWNS_VBO);
+
+}
diff --git a/source/blender/draw/engines/lanpr/lanpr_dpix.c b/source/blender/draw/engines/lanpr/lanpr_dpix.c
new file mode 100644 (file)
index 0000000..782746d
--- /dev/null
@@ -0,0 +1,396 @@
+#include "DRW_engine.h"
+#include "DRW_render.h"
+#include "BLI_listbase.h"
+#include "BLI_linklist.h"
+#include "lanpr_all.h"
+#include "DRW_render.h"
+#include "BKE_object.h"
+#include "DNA_mesh_types.h"
+#include "DNA_camera_types.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_framebuffer.h"
+#include "DNA_lanpr_types.h"
+#include "DNA_meshdata_types.h"
+#include "BKE_customdata.h"
+#include "DEG_depsgraph_query.h"
+#include "GPU_draw.h"
+
+#include "GPU_batch.h"
+#include "GPU_framebuffer.h"
+#include "GPU_shader.h"
+#include "GPU_uniformbuffer.h"
+#include "GPU_viewport.h"
+#include "bmesh.h"
+
+#include <math.h>
+
+extern LANPR_SharedResource lanpr_share;
+extern char datatoc_lanpr_dpix_project_passthrough_vert_glsl[];
+extern char datatoc_lanpr_dpix_project_clip_frag_glsl[];
+extern char datatoc_lanpr_dpix_preview_geom_glsl[];
+extern char datatoc_lanpr_dpix_preview_frag_glsl[];
+
+void lanpr_init_atlas_inputs(void *ved){
+       lanpr_share.ved_viewport = ved;
+       LANPR_Data *vedata = (LANPR_Data *)ved;
+       LANPR_TextureList *txl = vedata->txl;
+       LANPR_FramebufferList *fbl = vedata->fbl;
+       LANPR_StorageList *stl = ((LANPR_Data *)vedata)->stl;
+       DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+       const DRWContextState *draw_ctx = DRW_context_state_get();
+       View3D *v3d = draw_ctx->v3d;
+       RegionView3D *rv3d = draw_ctx->rv3d;
+       Object *camera = (rv3d && rv3d->persp == RV3D_CAMOB) ? v3d->camera : NULL;
+       SceneLANPR *lanpr = &draw_ctx->scene->lanpr;
+
+       if (lanpr->reloaded || !txl->dpix_in_pl) {
+               DRW_texture_ensure_2d(&txl->dpix_in_pl, TNS_DPIX_TEXTURE_SIZE, TNS_DPIX_TEXTURE_SIZE, GPU_RGBA32F, 0);
+               DRW_texture_ensure_2d(&txl->dpix_in_pr, TNS_DPIX_TEXTURE_SIZE, TNS_DPIX_TEXTURE_SIZE, GPU_RGBA32F, 0);
+               DRW_texture_ensure_2d(&txl->dpix_in_nl, TNS_DPIX_TEXTURE_SIZE, TNS_DPIX_TEXTURE_SIZE, GPU_RGBA32F, 0);
+               DRW_texture_ensure_2d(&txl->dpix_in_nr, TNS_DPIX_TEXTURE_SIZE, TNS_DPIX_TEXTURE_SIZE, GPU_RGBA32F, 0);
+               DRW_texture_ensure_2d(&txl->dpix_in_edge_mask, TNS_DPIX_TEXTURE_SIZE, TNS_DPIX_TEXTURE_SIZE, GPU_RGBA8, 0);
+               DRW_texture_ensure_2d(&txl->dpix_out_pl, TNS_DPIX_TEXTURE_SIZE, TNS_DPIX_TEXTURE_SIZE, GPU_RGBA32F, 0);
+               DRW_texture_ensure_2d(&txl->dpix_out_pr, TNS_DPIX_TEXTURE_SIZE, TNS_DPIX_TEXTURE_SIZE, GPU_RGBA32F, 0);
+               DRW_texture_ensure_2d(&txl->dpix_out_length, TNS_DPIX_TEXTURE_SIZE, TNS_DPIX_TEXTURE_SIZE, GPU_RGBA32F, 0);
+       }
+
+       GPU_framebuffer_ensure_config(&fbl->dpix_transform, {
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_TEXTURE(txl->dpix_out_pl),
+               GPU_ATTACHMENT_TEXTURE(txl->dpix_out_pr),
+               GPU_ATTACHMENT_TEXTURE(txl->dpix_out_length),
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE
+       });
+
+       GPU_framebuffer_ensure_config(&fbl->dpix_preview, {
+               GPU_ATTACHMENT_TEXTURE(txl->depth),
+               GPU_ATTACHMENT_TEXTURE(txl->color),
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE
+       });
+
+       if (!lanpr_share.dpix_transform_shader) {
+               lanpr_share.dpix_transform_shader =
+                       DRW_shader_create(
+                               datatoc_lanpr_dpix_project_passthrough_vert_glsl,
+                               NULL,
+                               datatoc_lanpr_dpix_project_clip_frag_glsl,
+                               NULL);
+       }
+       if (!lanpr_share.dpix_preview_shader) {
+               lanpr_share.dpix_preview_shader =
+                       DRW_shader_create(
+                               datatoc_lanpr_dpix_project_passthrough_vert_glsl,
+                               datatoc_lanpr_dpix_preview_geom_glsl,
+                               datatoc_lanpr_dpix_preview_frag_glsl,
+                               NULL);
+       }
+}
+void lanpr_destroy_atlas(void *ved){
+       //no need to free things, no custom data.
+}
+
+int lanpr_feed_atlas_data_obj(void *vedata,
+                              float *AtlasPointsL, float *AtlasPointsR,
+                              float *AtlasFaceNormalL, float *AtlasFaceNormalR,
+                              float *AtlasEdgeMask,
+                              Object *ob, int begin_index) {
+       LANPR_StorageList *stl = ((LANPR_Data *)vedata)->stl;
+
+       if (!DRW_object_is_renderable(ob)) return begin_index;
+       const DRWContextState *draw_ctx = DRW_context_state_get();
+       if (ob == draw_ctx->object_edit) return begin_index;
+       if (ob->type != OB_MESH) return begin_index;
+
+       Mesh *me = ob->data;
+       BMesh *bm;
+       struct BMFace *f1, *f2;
+       struct BMVert *v1, *v2;
+       struct BMEdge *e;
+       struct BMLoop *l1, *l2;
+       FreestyleEdge *fe;
+       int CanFindFreestyle = 0;
+       int vert_count = me->totvert, edge_count = me->totedge, face_count = me->totface;
+       int i, idx;
+
+       const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(me);
+       bm = BM_mesh_create(&allocsize,
+                           &((struct BMeshCreateParams) {.use_toolflags = true, }));
+       BM_mesh_bm_from_me(bm, me, &((struct BMeshFromMeshParams) {.calc_face_normal = true, }));
+       BM_mesh_elem_table_ensure(bm, BM_VERT | BM_EDGE | BM_FACE);
+
+       if (CustomData_has_layer(&bm->edata, CD_FREESTYLE_EDGE)) {
+               CanFindFreestyle = 1;
+       }
+
+       for (i = 0; i < edge_count; i++) {
+               f1 = 0;
+               f2 = 0;
+               e = BM_edge_at_index(bm, i);
+               v1 = e->v1;
+               v2 = e->v2;
+               l1 = e->l;
+               l2 = e->l ? e->l->radial_next : 0;
+               if (l1) f1 = l1->f;
+               if (l2) f2 = l2->f;
+
+               idx = (begin_index + i) * 4;
+
+               AtlasPointsL[idx + 0] = v1->co[0];
+               AtlasPointsL[idx + 1] = v1->co[1];
+               AtlasPointsL[idx + 2] = v1->co[2];
+               AtlasPointsL[idx + 3] = 1;
+
+               AtlasPointsR[idx + 0] = v2->co[0];
+               AtlasPointsR[idx + 1] = v2->co[1];
+               AtlasPointsR[idx + 2] = v2->co[2];
+               AtlasPointsR[idx + 3] = 1;
+
+               if (CanFindFreestyle) {
+                       fe = CustomData_bmesh_get(&bm->edata, e->head.data, CD_FREESTYLE_EDGE);
+                       if (fe->flag & FREESTYLE_EDGE_MARK) AtlasEdgeMask[idx + 1] = 1; // channel G
+               }
+
+               if (f1) {
+                       AtlasFaceNormalL[idx + 0] = f1->no[0];
+                       AtlasFaceNormalL[idx + 1] = f1->no[1];
+                       AtlasFaceNormalL[idx + 2] = f1->no[2];
+                       AtlasFaceNormalL[idx + 3] = 1;
+               }
+               else {
+                       AtlasFaceNormalL[idx + 0] = 0;
+                       AtlasFaceNormalL[idx + 1] = 0;
+                       AtlasFaceNormalL[idx + 2] = 0;
+                       AtlasFaceNormalL[idx + 3] = 0;
+               }
+
+               if (f2 && f2 != f1) { // this is for edge condition
+                       AtlasFaceNormalR[idx + 0] = f2->no[0];
+                       AtlasFaceNormalR[idx + 1] = f2->no[1];
+                       AtlasFaceNormalR[idx + 2] = f2->no[2];
+                       AtlasFaceNormalR[idx + 3] = 1;
+
+                       if (f2->mat_nr != f1->mat_nr) AtlasEdgeMask[idx] = 1; // channel R
+
+               }
+               else {
+                       AtlasFaceNormalR[idx + 0] = 0;
+                       AtlasFaceNormalR[idx + 1] = 0;
+                       AtlasFaceNormalR[idx + 2] = 0;
+                       AtlasFaceNormalR[idx + 3] = 0;
+               }
+
+       }
+
+       BM_mesh_free(bm);
+
+       return begin_index + edge_count;
+}
+
+int lanpr_feed_atlas_data_intersection_cache(void *vedata,
+                                             float *AtlasPointsL, float *AtlasPointsR,
+                                             float *AtlasFaceNormalL, float *AtlasFaceNormalR,
+                                             float *AtlasEdgeMask,
+                                             int begin_index) {
+       LANPR_StorageList *stl = ((LANPR_Data *)vedata)->stl;
+       LANPR_PrivateData *pd = stl->g_data;
+       const DRWContextState *draw_ctx = DRW_context_state_get();
+       SceneLANPR *lanpr = &draw_ctx->scene->lanpr;
+       LANPR_RenderBuffer *rb = lanpr->render_buffer;
+       nListItemPointer *lip;
+       LANPR_RenderLine *rl;
+       int i, idx;
+
+       i = 0;
+
+       if (!rb) return 0;
+
+       for (lip = rb->IntersectionLines.first; lip; lip = lip->pNext) {
+               rl = lip->p;
+
+               idx = (begin_index + i) * 4;
+               AtlasEdgeMask[idx + 2] = 1; // channel B
+
+               AtlasPointsL[idx + 0] = rl->L->GLocation[0];
+               AtlasPointsL[idx + 1] = rl->L->GLocation[1];
+               AtlasPointsL[idx + 2] = rl->L->GLocation[2];
+               AtlasPointsL[idx + 3] = 1;
+
+               AtlasPointsR[idx + 0] = rl->R->GLocation[0];
+               AtlasPointsR[idx + 1] = rl->R->GLocation[1];
+               AtlasPointsR[idx + 2] = rl->R->GLocation[2];
+               AtlasPointsR[idx + 3] = 1;
+
+               AtlasFaceNormalL[idx + 0] = 0;
+               AtlasFaceNormalL[idx + 1] = 0;
+               AtlasFaceNormalL[idx + 2] = 1;
+               AtlasFaceNormalL[idx + 3] = 0;
+
+               AtlasFaceNormalR[idx + 0] = 0;
+               AtlasFaceNormalR[idx + 1] = 0;
+               AtlasFaceNormalR[idx + 2] = 1;
+               AtlasFaceNormalR[idx + 3] = 0;
+
+               i++;
+       }
+
+       return begin_index + i;
+}
+
+void lanpr_dpix_index_to_coord(int index, float *x, float *y){
+       (*x) = tnsLinearItp(-1, 1, (float)(index % TNS_DPIX_TEXTURE_SIZE + 0.5) / (float)TNS_DPIX_TEXTURE_SIZE);
+       (*y) = tnsLinearItp(-1, 1, (float)(index / TNS_DPIX_TEXTURE_SIZE + 0.5) / (float)TNS_DPIX_TEXTURE_SIZE);
+}
+
+void lanpr_dpix_index_to_coord_absolute(int index, float *x, float *y){
+       (*x) = (float)(index % TNS_DPIX_TEXTURE_SIZE) + 0.5;
+       (*y) = (float)(index / TNS_DPIX_TEXTURE_SIZE) + 0.5;
+}
+
+int lanpr_feed_atlas_trigger_preview_obj(void *vedata, Object *ob, int begin_index) {
+       LANPR_StorageList *stl = ((LANPR_Data *)vedata)->stl;
+       LANPR_PrivateData *pd = stl->g_data;
+       Mesh *me = ob->data;
+       if (ob->type != OB_MESH) return begin_index;
+       int edge_count = me->totedge;
+       int i;
+       float co[2];
+
+       static GPUVertFormat format = { 0 };
+       static struct { uint pos, uvs; } attr_id;
+       if (format.attr_len == 0) {
+               attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+       }
+
+       static GPUVertFormat format2 = { 0 };
+       static struct { uint pos, uvs; } attr_id2;
+       if (format2.attr_len == 0) {
+               attr_id2.pos = GPU_vertformat_attr_add(&format2, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+       }
+
+       GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+       GPUVertBuf *vbo2 = GPU_vertbuf_create_with_format(&format2);
+       GPU_vertbuf_data_alloc(vbo, edge_count);
+       GPU_vertbuf_data_alloc(vbo2, edge_count);
+
+       for (i = 0; i < edge_count; i++) {
+               lanpr_dpix_index_to_coord(i + begin_index, &co[0], &co[1]);
+               GPU_vertbuf_attr_set(vbo, attr_id.pos, i, co);
+               lanpr_dpix_index_to_coord_absolute(i + begin_index, &co[0], &co[1]);
+               GPU_vertbuf_attr_set(vbo2, attr_id2.pos, i, co);
+       }
+
+       GPUBatch *gb = GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, 0, GPU_USAGE_STATIC | GPU_BATCH_OWNS_VBO);
+       GPUBatch *gb2 = GPU_batch_create_ex(GPU_PRIM_POINTS, vbo2, 0, GPU_USAGE_STATIC | GPU_BATCH_OWNS_VBO);
+
+       LANPR_BatchItem *bi = BLI_mempool_alloc(pd->mp_batch_list);
+       BLI_addtail(&pd->dpix_batch_list, bi);
+       bi->dpix_transform_batch = gb;
+       bi->dpix_preview_batch = gb2;
+       bi->ob = ob;
+
+       return begin_index + edge_count;
+}
+
+void lanpr_create_atlas_intersection_preview(void *vedata, int begin_index) {
+       LANPR_StorageList *stl = ((LANPR_Data *)vedata)->stl;
+       LANPR_PrivateData *pd = stl->g_data;
+       const DRWContextState *draw_ctx = DRW_context_state_get();
+       SceneLANPR *lanpr = &draw_ctx->scene->lanpr;
+       LANPR_RenderBuffer *rb = lanpr->render_buffer;
+       float co[2];
+       int i;
+
+       if (!rb) return;
+
+       if (rb->DPIXIntersectionBatch) GPU_batch_discard(rb->DPIXIntersectionBatch);
+       rb->DPIXIntersectionBatch = 0;
+
+       if (!rb->IntersectionCount) return;
+
+       static GPUVertFormat format = { 0 };
+       static struct { uint pos, uvs; } attr_id;
+       if (format.attr_len == 0) {
+               attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+       }
+       static GPUVertFormat format2 = { 0 };
+       static struct { uint pos, uvs; } attr_id2;
+       if (format2.attr_len == 0) {
+               attr_id2.pos = GPU_vertformat_attr_add(&format2, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+       }
+
+       GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+       GPU_vertbuf_data_alloc(vbo, rb->IntersectionCount);
+
+       GPUVertBuf *vbo2 = GPU_vertbuf_create_with_format(&format2);
+       GPU_vertbuf_data_alloc(vbo2, rb->IntersectionCount);
+
+       for (i = 0; i < rb->IntersectionCount; i++) {
+               lanpr_dpix_index_to_coord(i + begin_index, &co[0], &co[1]);
+               GPU_vertbuf_attr_set(vbo, attr_id.pos, i, co);
+               lanpr_dpix_index_to_coord_absolute(i + begin_index, &co[0], &co[1]);
+               GPU_vertbuf_attr_set(vbo2, attr_id2.pos, i, co);
+       }
+       rb->DPIXIntersectionTransformBatch = GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, 0, GPU_USAGE_STATIC | GPU_BATCH_OWNS_VBO);
+       rb->DPIXIntersectionBatch = GPU_batch_create_ex(GPU_PRIM_POINTS, vbo2, 0, GPU_USAGE_STATIC | GPU_BATCH_OWNS_VBO);
+}
+
+
+void lanpr_dpix_draw_scene(LANPR_TextureList *txl, LANPR_FramebufferList *fbl, LANPR_PassList *psl, LANPR_PrivateData *pd, SceneLANPR *lanpr, GPUFrameBuffer *DefaultFB, int is_render) {
+       float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+       float clear_depth = 1.0f;
+       uint clear_stencil = 0xFF;
+       int is_persp=1;
+
+       if (!lanpr->active_layer) return; /* return early in case we don't have line layers. DPIX only use the first layer. */
+
+       int texw = GPU_texture_width(txl->edge_intermediate), texh = GPU_texture_height(txl->edge_intermediate);;
+       int tsize = texw * texh;
+
+       const DRWContextState *draw_ctx = DRW_context_state_get();
+       Scene *scene = DEG_get_evaluated_scene(draw_ctx->depsgraph);
+       View3D *v3d = draw_ctx->v3d;
+       Object *camera = 0;
+       if (v3d) {
+               RegionView3D *rv3d = draw_ctx->rv3d;
+               camera = (rv3d && rv3d->persp == RV3D_CAMOB) ? v3d->camera : NULL;
+               is_persp = rv3d->is_persp;
+       }
+       if (!camera) {
+               camera = scene->camera;
+               if(!v3d)is_persp = ((Camera *)camera->data)->type == CAM_PERSP ? 1 : 0;
+       }
+       if (is_render && !camera) return;
+
+       //XXX: should implement view angle functions for ortho camera.
+
+       pd->dpix_viewport[2] = texw;
+       pd->dpix_viewport[3] = texh;
+       pd->dpix_is_perspective = is_persp;
+       pd->dpix_sample_step = 1;
+       pd->dpix_buffer_width = TNS_DPIX_TEXTURE_SIZE;
+       pd->dpix_depth_offset = 0.0001;
+       pd->dpix_znear = camera ? ((Camera *)camera->data)->clip_start : v3d->clip_start;
+       pd->dpix_zfar = camera ? ((Camera *)camera->data)->clip_end : v3d->clip_end;
+
+       GPU_point_size(1);
+       //GPU_line_width(2);
+       GPU_framebuffer_bind(fbl->dpix_transform);
+       DRW_draw_pass(psl->dpix_transform_pass);
+
+       GPU_framebuffer_bind(fbl->dpix_preview);
+       eGPUFrameBufferBits clear_bits = GPU_COLOR_BIT;
+       GPU_framebuffer_clear(fbl->dpix_preview, clear_bits, lanpr->background_color, clear_depth, clear_stencil);
+       DRW_draw_pass(psl->dpix_preview_pass);
+
+       GPU_framebuffer_bind(DefaultFB);
+       GPU_framebuffer_clear(DefaultFB, clear_bits, lanpr->background_color, clear_depth, clear_stencil);
+       DRW_multisamples_resolve(txl->depth, txl->color, 1);
+}
diff --git a/source/blender/draw/engines/lanpr/lanpr_engine.c b/source/blender/draw/engines/lanpr/lanpr_engine.c
new file mode 100644 (file)
index 0000000..a8d5f95
--- /dev/null
@@ -0,0 +1,674 @@
+#include "DRW_engine.h"
+#include "DRW_render.h"
+#include "BLI_listbase.h"
+#include "BLI_linklist.h"
+#include "BLI_math_matrix.h"
+#include "lanpr_all.h"
+#include "DRW_render.h"
+#include "BKE_object.h"
+#include "DNA_mesh_types.h"
+#include "DNA_camera_types.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_framebuffer.h"
+#include "DNA_lanpr_types.h"
+#include "GPU_draw.h"
+#include "DEG_depsgraph_query.h"
+#include "RE_pipeline.h"
+#include "BLI_rect.h"
+
+#include "GPU_batch.h"
+#include "GPU_framebuffer.h"
+#include "GPU_shader.h"
+#include "GPU_uniformbuffer.h"
+#include "GPU_viewport.h"
+#include "bmesh.h"
+
+#include <math.h>
+
+
+extern char datatoc_common_fullscreen_vert_glsl[];
+extern char datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl[];
+extern char datatoc_lanpr_snake_multichannel_frag_glsl[];
+extern char datatoc_lanpr_snake_edge_frag_glsl[];
+extern char datatoc_lanpr_snake_image_peel_frag_glsl[];
+extern char datatoc_lanpr_snake_line_connection_vert_glsl[];
+extern char datatoc_lanpr_snake_line_connection_frag_glsl[];
+extern char datatoc_lanpr_snake_line_connection_geom_glsl[];
+extern char datatoc_lanpr_software_line_chain_geom_glsl[];
+extern char datatoc_lanpr_software_chain_geom_glsl[];
+extern char datatoc_lanpr_dpix_project_passthrough_vert_glsl[];
+extern char datatoc_lanpr_dpix_project_clip_frag_glsl[];
+extern char datatoc_lanpr_dpix_preview_frag_glsl[];
+extern char datatoc_lanpr_software_passthrough_vert_glsl[];
+extern char datatoc_gpu_shader_2D_smooth_color_vert_glsl[];
+extern char datatoc_gpu_shader_2D_smooth_color_frag_glsl[];
+
+LANPR_SharedResource lanpr_share;
+
+
+static void lanpr_engine_init(void *ved){
+       lanpr_share.ved_viewport = ved;
+       LANPR_Data *vedata = (LANPR_Data *)ved;
+       LANPR_TextureList *txl = vedata->txl;
+       LANPR_FramebufferList *fbl = vedata->fbl;
+       LANPR_StorageList *stl = ((LANPR_Data *)vedata)->stl;
+       DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+       const DRWContextState *draw_ctx = DRW_context_state_get();
+       Scene *scene = DEG_get_evaluated_scene(draw_ctx->depsgraph);
+       SceneLANPR *lanpr = &scene->lanpr;
+       View3D *v3d = draw_ctx->v3d;
+
+       if (!lanpr_share.init_complete)
+               BLI_spin_init(&lanpr_share.render_flag_lock);
+
+       /* SNAKE */
+
+       DRW_texture_ensure_fullscreen_2D_multisample(&txl->depth, GPU_DEPTH_COMPONENT32F, 8, 0);
+       DRW_texture_ensure_fullscreen_2D_multisample(&txl->color, GPU_RGBA32F, 8, 0);
+       DRW_texture_ensure_fullscreen_2D_multisample(&txl->normal, GPU_RGBA32F, 8, 0);
+       DRW_texture_ensure_fullscreen_2D_multisample(&txl->edge_intermediate, GPU_RGBA32F, 8, 0);
+
+       DRW_texture_ensure_fullscreen_2D_multisample(&txl->ms_resolve_depth, GPU_DEPTH_COMPONENT32F, 8, 0);
+       DRW_texture_ensure_fullscreen_2D_multisample(&txl->ms_resolve_color, GPU_RGBA32F, 8, 0);
+
+
+       GPU_framebuffer_ensure_config(&fbl->passes, {
+               GPU_ATTACHMENT_TEXTURE(txl->depth),
+               GPU_ATTACHMENT_TEXTURE(txl->color),
+               GPU_ATTACHMENT_TEXTURE(txl->normal),
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE
+       });
+
+       GPU_framebuffer_ensure_config(&fbl->edge_intermediate, {
+               GPU_ATTACHMENT_TEXTURE(txl->depth),
+               GPU_ATTACHMENT_TEXTURE(txl->edge_intermediate),
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE
+       });
+
+       GPU_framebuffer_ensure_config(&fbl->edge_thinning, {
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_TEXTURE(txl->color),
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE
+       });
+
+
+       if (!lanpr_share.multichannel_shader) {
+               lanpr_share.multichannel_shader =
+                       DRW_shader_create(
+                               datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl,
+                               NULL,
+                               datatoc_lanpr_snake_multichannel_frag_glsl, 
+                               NULL);
+
+       }
+       if (!lanpr_share.edge_detect_shader) {
+               lanpr_share.edge_detect_shader =
+                       DRW_shader_create(
+                               datatoc_common_fullscreen_vert_glsl,
+                               NULL,
+                               datatoc_lanpr_snake_edge_frag_glsl,
+                               NULL);
+
+       }
+       if (!lanpr_share.edge_thinning_shader) {
+               lanpr_share.edge_thinning_shader =
+                       DRW_shader_create(
+                               datatoc_common_fullscreen_vert_glsl,
+                               NULL,
+                               datatoc_lanpr_snake_image_peel_frag_glsl, 
+                               NULL);
+
+       }
+       if (!lanpr_share.snake_connection_shader) {
+               lanpr_share.snake_connection_shader =
+                       DRW_shader_create(
+                               datatoc_lanpr_snake_line_connection_vert_glsl,
+                               datatoc_lanpr_snake_line_connection_geom_glsl,
+                               datatoc_lanpr_snake_line_connection_frag_glsl,
+                               NULL);
+       }
+
+       /* DPIX */
+       lanpr_init_atlas_inputs(ved);
+
+       /* SOFTWARE */
+       if (!lanpr_share.software_shader) {
+               lanpr_share.software_shader =
+                       DRW_shader_create(
+                               datatoc_lanpr_software_passthrough_vert_glsl,
+                               datatoc_lanpr_software_line_chain_geom_glsl,
+                               datatoc_lanpr_dpix_preview_frag_glsl,
+                               NULL);
+       }
+
+       if (!lanpr_share.software_chaining_shader) {
+               lanpr_share.software_chaining_shader =
+                       DRW_shader_create(
+                               datatoc_lanpr_software_passthrough_vert_glsl,
+                               datatoc_lanpr_software_chain_geom_glsl,
+                               datatoc_lanpr_dpix_preview_frag_glsl,
+                               NULL);
+       }
+
+       GPU_framebuffer_ensure_config(&fbl->software_ms, {
+               GPU_ATTACHMENT_TEXTURE(txl->ms_resolve_depth),
+               GPU_ATTACHMENT_TEXTURE(txl->ms_resolve_color),
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE
+       });
+
+       lanpr_share.init_complete = 1;
+
+}
+static void lanpr_engine_free(void){
+       void *ved = lanpr_share.ved_viewport;
+       LANPR_Data *vedata = (LANPR_Data *)ved;
+       LANPR_StorageList *stl = ((LANPR_Data *)vedata)->stl;
+
+       //only free custom data in storage list.
+
+       BLI_mempool_destroy(stl->g_data->mp_line_strip);
+       BLI_mempool_destroy(stl->g_data->mp_line_strip_point);
+       BLI_mempool_destroy(stl->g_data->mp_sample);
+       BLI_mempool_destroy(stl->g_data->mp_batch_list);
+
+       lanpr_destroy_atlas(vedata);
+
+       stl->g_data = 0;
+}
+
+void lanpr_calculate_normal_object_vector(LANPR_LineLayer* ll, float* normal_object_direction);
+
+static void lanpr_cache_init(void *vedata){
+
+       LANPR_PassList *psl = ((LANPR_Data *)vedata)->psl;
+       LANPR_StorageList *stl = ((LANPR_Data *)vedata)->stl;
+       LANPR_TextureList *txl = ((LANPR_Data *)vedata)->txl;
+
+       DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+       static float normal_object_direction[3] = { 0,0,1 };
+
+       if (!stl->g_data) {
+               /* Alloc transient pointers */
+               stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
+               stl->g_data->mp_sample = BLI_mempool_create(sizeof(LANPR_TextureSample), 0, 512, BLI_MEMPOOL_NOP);
+               stl->g_data->mp_line_strip = BLI_mempool_create(sizeof(LANPR_LineStrip), 0, 512, BLI_MEMPOOL_NOP);
+               stl->g_data->mp_line_strip_point = BLI_mempool_create(sizeof(LANPR_LineStripPoint), 0, 1024, BLI_MEMPOOL_NOP);
+               stl->g_data->mp_batch_list = BLI_mempool_create(sizeof(LANPR_BatchItem), 0, 128, BLI_MEMPOOL_NOP);
+       }
+
+       LANPR_PrivateData *pd = stl->g_data;
+
+       const DRWContextState *draw_ctx = DRW_context_state_get();
+       Scene *scene = DEG_get_evaluated_scene(draw_ctx->depsgraph);
+       SceneLANPR *lanpr = &scene->lanpr;
+       View3D *v3d = draw_ctx->v3d;
+
+       psl->color_pass = DRW_pass_create("color Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WRITE_DEPTH);
+       stl->g_data->multipass_shgrp = DRW_shgroup_create(lanpr_share.multichannel_shader, psl->color_pass);
+
+
+       if (lanpr->master_mode == LANPR_MASTER_MODE_SNAKE) {
+               struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
+
+               psl->edge_intermediate = DRW_pass_create("Edge Detection", DRW_STATE_WRITE_COLOR);
+               stl->g_data->edge_detect_shgrp = DRW_shgroup_create(lanpr_share.edge_detect_shader, psl->edge_intermediate);
+               DRW_shgroup_uniform_texture_ref(stl->g_data->edge_detect_shgrp, "tex_sample_0", &txl->depth);
+               DRW_shgroup_uniform_texture_ref(stl->g_data->edge_detect_shgrp, "tex_sample_1", &txl->color);
+               DRW_shgroup_uniform_texture_ref(stl->g_data->edge_detect_shgrp, "tex_sample_2", &txl->normal);
+
+               DRW_shgroup_uniform_float(stl->g_data->edge_detect_shgrp, "z_near", &stl->g_data->znear, 1);
+               DRW_shgroup_uniform_float(stl->g_data->edge_detect_shgrp, "z_far", &stl->g_data->zfar, 1);
+
+               DRW_shgroup_uniform_float(stl->g_data->edge_detect_shgrp, "normal_clamp", &stl->g_data->normal_clamp, 1);// normal clamp
+               DRW_shgroup_uniform_float(stl->g_data->edge_detect_shgrp, "normal_strength", &stl->g_data->normal_strength, 1);// normal strength
+               DRW_shgroup_uniform_float(stl->g_data->edge_detect_shgrp, "depth_clamp", &stl->g_data->depth_clamp, 1);// depth clamp
+               DRW_shgroup_uniform_float(stl->g_data->edge_detect_shgrp, "depth_strength", &stl->g_data->depth_strength, 1);// depth strength
+               DRW_shgroup_call_add(stl->g_data->edge_detect_shgrp, quad, NULL);
+
+               psl->edge_thinning = DRW_pass_create("Edge Thinning Stage 1", DRW_STATE_WRITE_COLOR);
+               stl->g_data->edge_thinning_shgrp = DRW_shgroup_create(lanpr_share.edge_thinning_shader, psl->edge_thinning);
+               DRW_shgroup_uniform_texture_ref(stl->g_data->edge_thinning_shgrp, "tex_sample_0", &dtxl->color);
+               DRW_shgroup_uniform_int(stl->g_data->edge_thinning_shgrp, "stage", &stl->g_data->stage, 1);
+               DRW_shgroup_call_add(stl->g_data->edge_thinning_shgrp, quad, NULL);
+
+       }
+       elif(lanpr->master_mode == LANPR_MASTER_MODE_DPIX && lanpr->active_layer)
+       {
+               LANPR_LineLayer *ll = lanpr->line_layers.first;
+               psl->dpix_transform_pass = DRW_pass_create("DPIX Transform Stage", DRW_STATE_WRITE_COLOR);
+               stl->g_data->dpix_transform_shgrp = DRW_shgroup_create(lanpr_share.dpix_transform_shader, psl->dpix_transform_pass);
+               DRW_shgroup_uniform_texture_ref(stl->g_data->dpix_transform_shgrp, "vert0_tex", &txl->dpix_in_pl);
+               DRW_shgroup_uniform_texture_ref(stl->g_data->dpix_transform_shgrp, "vert1_tex", &txl->dpix_in_pr);
+               DRW_shgroup_uniform_texture_ref(stl->g_data->dpix_transform_shgrp, "face_normal0_tex", &txl->dpix_in_nl);
+               DRW_shgroup_uniform_texture_ref(stl->g_data->dpix_transform_shgrp, "face_normal1_tex", &txl->dpix_in_nr);
+               DRW_shgroup_uniform_texture_ref(stl->g_data->dpix_transform_shgrp, "edge_mask_tex", &txl->dpix_in_edge_mask);
+               DRW_shgroup_uniform_int(stl->g_data->dpix_transform_shgrp, "sample_step", &stl->g_data->dpix_sample_step, 1);
+               DRW_shgroup_uniform_int(stl->g_data->dpix_transform_shgrp, "is_perspective", &stl->g_data->dpix_is_perspective, 1);
+               DRW_shgroup_uniform_vec4(stl->g_data->dpix_transform_shgrp, "viewport", stl->g_data->dpix_viewport, 1);
+               DRW_shgroup_uniform_int(stl->g_data->dpix_transform_shgrp, "buffer_width", &stl->g_data->dpix_buffer_width, 1);
+               DRW_shgroup_uniform_float(stl->g_data->dpix_transform_shgrp, "crease_threshold", &lanpr->crease_threshold, 1);
+               DRW_shgroup_uniform_float(stl->g_data->dpix_transform_shgrp, "crease_fade_threshold", &lanpr->crease_fade_threshold, 1);
+               DRW_shgroup_uniform_int(stl->g_data->dpix_transform_shgrp, "enable_crease", &ll->enable_crease, 1);
+               DRW_shgroup_uniform_int(stl->g_data->dpix_transform_shgrp, "enable_material", &ll->enable_material_seperate, 1);
+               DRW_shgroup_uniform_int(stl->g_data->dpix_transform_shgrp, "enable_edge_mark", &ll->enable_edge_mark, 1);
+               DRW_shgroup_uniform_int(stl->g_data->dpix_transform_shgrp, "enable_intersection", &ll->enable_intersection, 1);
+
+               psl->dpix_preview_pass = DRW_pass_create("DPIX Preview", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL);
+               stl->g_data->dpix_preview_shgrp = DRW_shgroup_create(lanpr_share.dpix_preview_shader, psl->dpix_preview_pass);
+               DRW_shgroup_uniform_texture_ref(stl->g_data->dpix_preview_shgrp, "vert0_tex", &txl->dpix_out_pl);
+               DRW_shgroup_uniform_texture_ref(stl->g_data->dpix_preview_shgrp, "vert1_tex", &txl->dpix_out_pr);
+               DRW_shgroup_uniform_texture_ref(stl->g_data->dpix_preview_shgrp, "face_normal0_tex", &txl->dpix_in_nl);
+               DRW_shgroup_uniform_texture_ref(stl->g_data->dpix_preview_shgrp, "face_normal1_tex", &txl->dpix_in_nr);// these are for normal shading
+               DRW_shgroup_uniform_texture_ref(stl->g_data->dpix_preview_shgrp, "edge_mask_tex", &txl->dpix_in_edge_mask);
+               DRW_shgroup_uniform_vec4(stl->g_data->dpix_preview_shgrp, "viewport", stl->g_data->dpix_viewport, 1);
+               DRW_shgroup_uniform_vec4(stl->g_data->dpix_preview_shgrp, "color", ll->color, 1);
+               DRW_shgroup_uniform_vec4(stl->g_data->dpix_preview_shgrp, "crease_color", ll->crease_color, 1);
+               DRW_shgroup_uniform_vec4(stl->g_data->dpix_preview_shgrp, "material_color", ll->material_color, 1);
+               DRW_shgroup_uniform_vec4(stl->g_data->dpix_preview_shgrp, "edge_mark_color", ll->edge_mark_color, 1);
+               DRW_shgroup_uniform_vec4(stl->g_data->dpix_preview_shgrp, "intersection_color", ll->intersection_color, 1);
+               DRW_shgroup_uniform_vec4(stl->g_data->dpix_preview_shgrp, "background_color", lanpr->background_color, 1);
+               //DRW_shgroup_uniform_vec4(stl->g_data->dpix_preview_shgrp, "line_color", ll->line_color, 1); //we have color
+               DRW_shgroup_uniform_float(stl->g_data->dpix_preview_shgrp, "depth_offset", &stl->g_data->dpix_depth_offset, 1);
+               DRW_shgroup_uniform_float(stl->g_data->dpix_preview_shgrp, "depth_width_influence", &lanpr->depth_width_influence, 1);
+               DRW_shgroup_uniform_float(stl->g_data->dpix_preview_shgrp, "depth_width_curve", &lanpr->depth_width_curve, 1);
+               DRW_shgroup_uniform_float(stl->g_data->dpix_preview_shgrp, "depth_alpha_influence", &lanpr->depth_alpha_influence, 1);
+               DRW_shgroup_uniform_float(stl->g_data->dpix_preview_shgrp, "depth_alpha_curve", &lanpr->depth_alpha_curve, 1);
+               DRW_shgroup_uniform_float(stl->g_data->dpix_preview_shgrp, "line_thickness", &ll->thickness, 1);
+               DRW_shgroup_uniform_float(stl->g_data->dpix_preview_shgrp, "line_thickness_crease", &ll->thickness_crease, 1);
+               DRW_shgroup_uniform_float(stl->g_data->dpix_preview_shgrp, "line_thickness_material", &ll->thickness_material, 1);
+               DRW_shgroup_uniform_float(stl->g_data->dpix_preview_shgrp, "line_thickness_edge_mark", &ll->thickness_edge_mark, 1);
+               DRW_shgroup_uniform_float(stl->g_data->dpix_preview_shgrp, "line_thickness_intersection", &ll->thickness_intersection, 1);
+               DRW_shgroup_uniform_float(stl->g_data->dpix_preview_shgrp, "z_near", &stl->g_data->dpix_znear, 1);
+               DRW_shgroup_uniform_float(stl->g_data->dpix_preview_shgrp, "z_far", &stl->g_data->dpix_zfar, 1);
+
+               lanpr_calculate_normal_object_vector(ll, normal_object_direction);
+
+               DRW_shgroup_uniform_int(stl->g_data->dpix_preview_shgrp, "normal_mode", &ll->normal_mode, 1);
+               DRW_shgroup_uniform_int(stl->g_data->dpix_preview_shgrp, "normal_effect_inverse", &ll->normal_effect_inverse, 1);
+               DRW_shgroup_uniform_float(stl->g_data->dpix_preview_shgrp, "normal_ramp_begin", &ll->normal_ramp_begin, 1);
+               DRW_shgroup_uniform_float(stl->g_data->dpix_preview_shgrp, "normal_ramp_end", &ll->normal_ramp_end, 1);
+               DRW_shgroup_uniform_float(stl->g_data->dpix_preview_shgrp, "normal_thickness_begin", &ll->normal_thickness_begin, 1);
+               DRW_shgroup_uniform_float(stl->g_data->dpix_preview_shgrp, "normal_thickness_end", &ll->normal_thickness_end, 1);
+               DRW_shgroup_uniform_vec3(stl->g_data->dpix_preview_shgrp, "normal_direction", normal_object_direction, 1);
+
+               pd->begin_index = 0;
+               int fsize = sizeof(float) * 4 * TNS_DPIX_TEXTURE_SIZE * TNS_DPIX_TEXTURE_SIZE;
+
+               if (lanpr->reloaded) {
+                       pd->atlas_pl = MEM_callocN(fsize, "atlas_point_l");
+                       pd->atlas_pr = MEM_callocN(fsize, "atlas_point_r");
+                       pd->atlas_nl = MEM_callocN(fsize, "atlas_normal_l");
+                       pd->atlas_nr = MEM_callocN(fsize, "atlas_normal_l");
+                       pd->atlas_edge_mask = MEM_callocN(fsize, "atlas_edge_mask"); // should always be float
+
+                       pd->dpix_batch_list.first = pd->dpix_batch_list.last = 0;
+                       BLI_mempool_clear(pd->mp_batch_list);
+               }
+       } elif(lanpr->master_mode == LANPR_MASTER_MODE_SOFTWARE)
+       {
+               ;
+       }
+
+
+
+}
+
+static void lanpr_cache_populate(void *vedata, Object *ob){
+
+       LANPR_StorageList *stl = ((LANPR_Data *)vedata)->stl;
+       LANPR_PrivateData *pd = stl->g_data;
+       const DRWContextState *draw_ctx = DRW_context_state_get();
+       View3D *v3d = draw_ctx->v3d;
+       SceneLANPR *lanpr = &draw_ctx->scene->lanpr;
+
+       if (!DRW_object_is_renderable(ob)) return;
+       if (ob == draw_ctx->object_edit) return;
+       if (ob->type != OB_MESH) return;
+
+       struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
+       if (geom) {
+               DRW_shgroup_call_object_add_no_cull(stl->g_data->multipass_shgrp, geom, ob);
+       }
+
+       if (lanpr->master_mode == LANPR_MASTER_MODE_DPIX && lanpr->active_layer) {
+               int idx = pd->begin_index;
+               if (lanpr->reloaded) {
+                       pd->begin_index = lanpr_feed_atlas_data_obj(vedata, pd->atlas_pl, pd->atlas_pr, pd->atlas_nl, pd->atlas_nr, pd->atlas_edge_mask, ob, idx);
+                       lanpr_feed_atlas_trigger_preview_obj(vedata, ob, idx);
+               }
+
+       }
+}
+
+static void lanpr_cache_finish(void *vedata){
+       LANPR_StorageList *stl = ((LANPR_Data *)vedata)->stl;
+       LANPR_PrivateData *pd = stl->g_data;
+       LANPR_TextureList *txl = ((LANPR_Data *)vedata)->txl;
+       const DRWContextState *draw_ctx = DRW_context_state_get();
+       View3D *v3d = draw_ctx->v3d;
+       SceneLANPR *lanpr = &draw_ctx->scene->lanpr;
+       float mat[4][4];
+       unit_m4(mat);
+
+       if (lanpr->master_mode == LANPR_MASTER_MODE_DPIX && lanpr->active_layer) {
+               if (lanpr->reloaded) {
+                       if (lanpr->render_buffer) {
+                               lanpr_feed_atlas_data_intersection_cache(vedata, pd->atlas_pl, pd->atlas_pr, pd->atlas_nl, pd->atlas_nr, pd->atlas_edge_mask, pd->begin_index);
+                               lanpr_create_atlas_intersection_preview(vedata, pd->begin_index);
+                       }
+                       GPU_texture_update(txl->dpix_in_pl, GPU_DATA_FLOAT, pd->atlas_pl);
+                       GPU_texture_update(txl->dpix_in_pr, GPU_DATA_FLOAT, pd->atlas_pr);
+                       GPU_texture_update(txl->dpix_in_nl, GPU_DATA_FLOAT, pd->atlas_nl);
+                       GPU_texture_update(txl->dpix_in_nr, GPU_DATA_FLOAT, pd->atlas_nr);
+                       GPU_texture_update(txl->dpix_in_edge_mask, GPU_DATA_FLOAT, pd->atlas_edge_mask);
+
+                       MEM_freeN(pd->atlas_pl);
+                       MEM_freeN(pd->atlas_pr);
+                       MEM_freeN(pd->atlas_nl);
+                       MEM_freeN(pd->atlas_nr);
+                       MEM_freeN(pd->atlas_edge_mask);
+                       pd->atlas_pl = 0;
+                       lanpr->reloaded = 0;
+               }
+
+
+
+               LANPR_BatchItem *bi;
+               for (bi = pd->dpix_batch_list.first; bi; bi = (void *)bi->Item.next) {
+                       DRW_shgroup_call_add(pd->dpix_transform_shgrp, bi->dpix_transform_batch, bi->ob->obmat);
+                       DRW_shgroup_call_add(pd->dpix_preview_shgrp, bi->dpix_preview_batch, 0);
+               }
+
+               if (lanpr->render_buffer && lanpr->render_buffer->DPIXIntersectionBatch) {
+                       DRW_shgroup_call_add(pd->dpix_transform_shgrp, lanpr->render_buffer->DPIXIntersectionTransformBatch, 0);
+                       DRW_shgroup_call_add(pd->dpix_preview_shgrp, lanpr->render_buffer->DPIXIntersectionBatch, 0);
+               }
+       }
+}
+
+void lanpr_batch_free(SceneLANPR *lanpr) {
+
+}
+
+// below are commented to prevent interface lock in some conditions.
+// should look into it,
+void lanpr_set_render_flag() {
+       //BLI_spin_lock(&lanpr_share.render_flag_lock);
+       //lanpr_share.during_render = 1;
+       //BLI_spin_unlock(&lanpr_share.render_flag_lock);
+}
+void lanpr_clear_render_flag() {
+       //BLI_spin_lock(&lanpr_share.render_flag_lock);
+       //lanpr_share.during_render = 0;
+       //BLI_spin_unlock(&lanpr_share.render_flag_lock);
+}
+int lanpr_during_render() {
+       int status;
+       BLI_spin_lock(&lanpr_share.render_flag_lock);
+       status = lanpr_share.during_render;
+       BLI_spin_unlock(&lanpr_share.render_flag_lock);
+       return status;
+}
+
+static void lanpr_draw_scene_exec(void *vedata, GPUFrameBuffer *dfb, int is_render) {
+       LANPR_PassList *psl = ((LANPR_Data *)vedata)->psl;
+       LANPR_TextureList *txl = ((LANPR_Data *)vedata)->txl;
+       LANPR_StorageList *stl = ((LANPR_Data *)vedata)->stl;
+       LANPR_FramebufferList *fbl = ((LANPR_Data *)vedata)->fbl;
+       LANPR_PrivateData *pd = stl->g_data;
+
+       float clear_col[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
+       float clear_depth = 1.0f;
+       uint clear_stencil = 0xFF;
+
+       GPU_framebuffer_bind(fbl->passes);
+       eGPUFrameBufferBits clear_bits = GPU_DEPTH_BIT | GPU_COLOR_BIT;
+       GPU_framebuffer_clear(fbl->passes, clear_bits, clear_col, clear_depth, clear_stencil);
+
+       const DRWContextState *draw_ctx = DRW_context_state_get();
+       Scene *scene = DEG_get_evaluated_scene(draw_ctx->depsgraph);
+       SceneLANPR *lanpr = &scene->lanpr;
+       View3D *v3d = draw_ctx->v3d;
+
+       if (lanpr->master_mode == LANPR_MASTER_MODE_DPIX) {
+               DRW_draw_pass(psl->color_pass);
+               lanpr_dpix_draw_scene(txl, fbl, psl, stl->g_data, lanpr, dfb, is_render);
+       }
+       elif(lanpr->master_mode == LANPR_MASTER_MODE_SNAKE)
+       {
+               DRW_draw_pass(psl->color_pass);
+               lanpr_snake_draw_scene(txl, fbl, psl, stl->g_data, lanpr, dfb, is_render);
+       }
+       elif(lanpr->master_mode == LANPR_MASTER_MODE_SOFTWARE)
+       {
+               // should isolate these into a seperate function.
+               lanpr_software_draw_scene(vedata, dfb, is_render);
+       }
+}
+
+static void lanpr_draw_scene(void *vedata) {
+       DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+       lanpr_draw_scene_exec(vedata, dfbl->default_fb, 0);
+}
+
+void LANPR_render_cache(
+       void *vedata, struct Object *ob,
+       struct RenderEngine *engine, struct Depsgraph *UNUSED(depsgraph)){
+
+       lanpr_cache_populate(vedata, ob);
+
+}
+
+static void workbench_render_matrices_init(RenderEngine *engine, Depsgraph *depsgraph)
+{
+       /* TODO(sergey): Shall render hold pointer to an evaluated camera instead? */
+       Scene *scene = DEG_get_evaluated_scene(depsgraph);
+       struct Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re));
+       float frame = BKE_scene_frame_get(scene);
+
+       /* Set the persective, view and window matrix. */
+       float winmat[4][4], wininv[4][4];
+       float viewmat[4][4], viewinv[4][4];
+       float persmat[4][4], persinv[4][4];
+       float unitmat[4][4];
+
+       RE_GetCameraWindow(engine->re, ob_camera_eval, frame, winmat);
+       RE_GetCameraModelMatrix(engine->re, ob_camera_eval, viewinv);
+
+       invert_m4_m4(viewmat, viewinv);
+       mul_m4_m4m4(persmat, winmat, viewmat);
+       invert_m4_m4(persinv, persmat);
+       invert_m4_m4(wininv, winmat);
+
+       unit_m4(unitmat);
+
+       DRW_viewport_matrix_override_set(persmat, DRW_MAT_PERS);
+       DRW_viewport_matrix_override_set(persinv, DRW_MAT_PERSINV);
+       DRW_viewport_matrix_override_set(winmat, DRW_MAT_WIN);
+       DRW_viewport_matrix_override_set(wininv, DRW_MAT_WININV);
+       DRW_viewport_matrix_override_set(viewmat, DRW_MAT_VIEW);
+       DRW_viewport_matrix_override_set(viewinv, DRW_MAT_VIEWINV);
+}
+
+int lanpr_compute_feature_lines_internal(Depsgraph *depsgraph, SceneLANPR *lanpr, Scene *scene);
+LANPR_RenderBuffer *lanpr_create_render_buffer(SceneLANPR *lanpr);
+
+extern DrawEngineType draw_engine_lanpr_type;
+
+static int LANPR_GLOBAL_update_tag;
+
+void lanpr_id_update(LANPR_Data *vedata, ID *id){
+       //if (vedata->engine_type != &draw_engine_lanpr_type) return;
+
+       /* Handle updates based on ID type. */
+       switch (GS(id->name)) {
+       case ID_WO:
+       case ID_OB:
+       case ID_ME:
+               LANPR_GLOBAL_update_tag = 1;
+       default:
+               /* pass */
+               break;
+       }
+}
+
+static void lanpr_render_to_image(LANPR_Data *vedata, RenderEngine *engine, struct RenderLayer *render_layer, const rcti *rect){
+       LANPR_StorageList *stl = vedata->stl;
+       LANPR_TextureList *txl = vedata->txl;
+       LANPR_FramebufferList *fbl = vedata->fbl;
+       const DRWContextState *draw_ctx = DRW_context_state_get();
+       //int update_mark = DEG_id_type_any_updated(draw_ctx->depsgraph);
+       Scene *scene = DEG_get_evaluated_scene(draw_ctx->depsgraph);
+       SceneLANPR *lanpr = &scene->lanpr;
+
+
+       lanpr_set_render_flag();
+
+       if (lanpr->master_mode == LANPR_MASTER_MODE_SOFTWARE ||
+           (lanpr->master_mode == LANPR_MASTER_MODE_DPIX && lanpr->enable_intersections)) {
+               if (!lanpr->render_buffer) lanpr_create_render_buffer(lanpr);
+               if (lanpr->render_buffer->cached_for_frame != scene->r.cfra || LANPR_GLOBAL_update_tag) {
+                       lanpr_compute_feature_lines_internal(draw_ctx->depsgraph, lanpr, scene);
+               }
+       }
+
+       workbench_render_matrices_init(engine, draw_ctx->depsgraph);
+
+       /* refered to eevee's code */
+
+       /* Init default FB and render targets:
+        * In render mode the default framebuffer is not generated
+        * because there is no viewport. So we need to manually create it or
+        * not use it. For code clarity we just allocate it make use of it. */
+       DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+       DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+       DRW_texture_ensure_fullscreen_2d(&dtxl->depth, GPU_DEPTH_COMPONENT32F, 0);
+       DRW_texture_ensure_fullscreen_2d(&dtxl->color, GPU_RGBA32F, 0);
+
+       GPU_framebuffer_ensure_config(&dfbl->default_fb, {
+               GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+               GPU_ATTACHMENT_TEXTURE(dtxl->color),
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE,
+               GPU_ATTACHMENT_LEAVE
+       });
+
+       lanpr_engine_init(vedata);
+       lanpr->reloaded = 1; // force dpix batch to re-create
+       lanpr_cache_init(vedata);
+       DRW_render_object_iter(vedata, engine, draw_ctx->depsgraph, LANPR_render_cache);
+       lanpr_cache_finish(vedata);
+
+       DRW_render_instance_buffer_finish();
+
+       float clear_col[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
+       float clear_depth = 1.0f;
+       uint clear_stencil = 0xFF;
+       eGPUFrameBufferBits clear_bits = GPU_DEPTH_BIT | GPU_COLOR_BIT;
+
+       GPU_framebuffer_bind(dfbl->default_fb);
+       GPU_framebuffer_clear(dfbl->default_fb, clear_bits, clear_col, clear_depth, clear_stencil);
+
+       lanpr_draw_scene_exec(vedata, dfbl->default_fb, 1);
+
+       // read it back so we can again display and save it.
+       const char *viewname = RE_GetActiveRenderView(engine->re);
+       RenderPass *rp = RE_pass_find_by_name(render_layer, RE_PASSNAME_COMBINED, viewname);
+       GPU_framebuffer_bind(dfbl->default_fb);
+       GPU_framebuffer_read_color(dfbl->default_fb,
+                                  rect->xmin, rect->ymin,
+                                  BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
+                                  4, 0, rp->rect);
+
+       //we don't need to free pass/buffer/texture in the engine's list
+       //lanpr_engine_free();
+
+       lanpr_clear_render_flag();
+}
+
+static void lanpr_view_update(void *vedata){
+       //LANPR_StorageList *stl = ((LANPR_Data *)vedata)->stl;
+       //if (stl->g_data) {
+       //      stl->g_data->view_updated = true;
+       //}
+
+       //our update flag is in SceneLANPR.
+       const DRWContextState *draw_ctx = DRW_context_state_get();
+       SceneLANPR *lanpr = &DEG_get_evaluated_scene(draw_ctx->depsgraph)->lanpr;
+       lanpr->reloaded = 1; // very bad solution, this will slow down animation.
+}
+
+//static void lanpr_id_update(void *vedata, ID *id){
+//     const DRWContextState *draw_ctx = DRW_context_state_get();
+//    SceneLANPR *lanpr = &DEG_get_evaluated_scene(draw_ctx->depsgraph)->lanpr;
+//
+//     /* look at eevee_engine.c */
+//     switch (GS(id->name)) {
+//             case ID_OB:
+//                 //seems doesn't need this one currently...
+//                     //eevee_id_object_update(vedata, (Object *)id);
+//                     lanpr->reloaded = 1;
+//                     break;
+//             case ID_ME:
+//                 lanpr->reloaded=1;
+//                     break;
+//             default:
+//                     /* pass */
+//                     break;
+//     }
+//}
+
+
+static const DrawEngineDataSize lanpr_data_size = DRW_VIEWPORT_DATA_SIZE(LANPR_Data);
+
+DrawEngineType draw_engine_lanpr_type = {
+       NULL, NULL,
+       N_("LANPR"),
+       &lanpr_data_size, // why should we have the "&" ?
+       &lanpr_engine_init,
+       &lanpr_engine_free,
+       &lanpr_cache_init,
+       &lanpr_cache_populate,
+       &lanpr_cache_finish,
+       NULL,//draw background
+       &lanpr_draw_scene,//draw scene, looks like that not much difference except a camera overlay image.
+       &lanpr_view_update,
+       &lanpr_id_update, //&lanpr_id_update, wait till I figure out how to do this.
+       &lanpr_render_to_image,
+};
+
+RenderEngineType DRW_engine_viewport_lanpr_type = {
+       NULL, NULL,
+       LANPR_ENGINE, N_("LANPR"), RE_INTERNAL,
+       NULL,// update
+       &DRW_render_to_image,// render to img
+       NULL,// bake
+       NULL,// doesn't seem to be what I thought it was... &lanpr_view_update,// view update
+       NULL,// render to view
+       NULL,// update in script
+       NULL,// update in render pass
+       &draw_engine_lanpr_type,
+       {NULL, NULL, NULL}
+};
+
diff --git a/source/blender/draw/engines/lanpr/lanpr_ops.c b/source/blender/draw/engines/lanpr/lanpr_ops.c
new file mode 100644 (file)
index 0000000..104a881
--- /dev/null
@@ -0,0 +1,3799 @@
+#include "DRW_engine.h"
+#include "DRW_render.h"
+#include "BLI_listbase.h"
+#include "BLI_linklist.h"
+#include "BLI_math_matrix.h"
+#include "BLI_task.h"
+#include "BLI_utildefines.h"
+#include "lanpr_all.h"
+#include "lanpr_util.h"
+#include "DRW_render.h"
+#include "BKE_object.h"
+#include "DNA_mesh_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_modifier_types.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_framebuffer.h"
+#include "DNA_lanpr_types.h"
+#include "DNA_meshdata_types.h"
+#include "BKE_customdata.h"
+#include "DEG_depsgraph_query.h"
+#include "BKE_camera.h"
+#include "BKE_collection.h"
+#include "BKE_report.h"
+#include "GPU_draw.h"
+
+#include "GPU_batch.h"
+#include "GPU_framebuffer.h"
+#include "GPU_shader.h"
+#include "GPU_uniformbuffer.h"
+#include "GPU_viewport.h"
+#include "bmesh.h"
+#include "bmesh_class.h"
+#include "bmesh_tools.h"
+
+#include "WM_types.h"
+#include "WM_api.h"
+
+#include <math.h>
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+/*
+
+   Ported from NUL4.0
+
+   Author(s):WuYiming - xp8110@outlook.com
+
+ */
+
+struct Object;
+
+
+int lanpr_triangle_line_imagespace_intersection_v2(SpinLock *spl, LANPR_RenderTriangle *rt, LANPR_RenderLine *rl, Object *cam, tnsMatrix44d vp, real *CameraDir, double *From, double *To);
+void lanpr_compute_view_vector(LANPR_RenderBuffer *rb);
+
+int use_smooth_contour_modifier_contour = 0; // debug purpose
+
+/* ====================================== base structures =========================================== */
+
+#define TNS_BOUND_AREA_CROSSES(b1, b2) \
+       ((b1)[0] < (b2)[1] && (b1)[1] > (b2)[0] && (b1)[3] < (b2)[2] && (b1)[2] > (b2)[3])
+
+void lanpr_make_initial_bounding_areas(LANPR_RenderBuffer *rb) {
+       int sp_w = 4;//20;
+       int sp_h = 4;//rb->H / (rb->W / sp_w);
+       int row, col;
+       LANPR_BoundingArea *ba;
+       real W = (real)rb->W;
+       real H = (real)rb->H;
+       real span_w = (real)1 / sp_w * 2.0;
+       real span_h = (real)1 / sp_h * 2.0;
+
+       rb->TileCountX = sp_w;
+       rb->TileCountY = sp_h;
+       rb->WidthPerTile = span_w;
+       rb->HeightPerTile = span_h;
+
+       rb->BoundingAreaCount = sp_w * sp_h;
+       rb->InitialBoundingAreas = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_BoundingArea) * rb->BoundingAreaCount);
+
+       for (row = 0; row < sp_h; row++) {
+               for (col = 0; col < sp_w; col++) {
+                       ba = &rb->InitialBoundingAreas[row * 4 + col];
+
+                       ba->L = span_w * col - 1.0;
+                       ba->R = (col == sp_w - 1) ? 1.0 : (span_w * (col + 1) - 1.0);
+                       ba->U = 1.0 - span_h * row;
+                       ba->B = (row == sp_h - 1) ? -1.0 : (1.0 - span_h * (row + 1));
+
+                       ba->CX = (ba->L + ba->R) / 2;
+                       ba->CY = (ba->U + ba->B) / 2;
+
+                       if (row) {
+                               list_append_pointer_static(&ba->UP, &rb->RenderDataPool, &rb->InitialBoundingAreas[(row - 1) * 4 + col]);
+                       }
+                       if (col) {
+                               list_append_pointer_static(&ba->LP, &rb->RenderDataPool, &rb->InitialBoundingAreas[row * 4 + col - 1]);
+                       }
+                       if (row != sp_h - 1) {
+                               list_append_pointer_static(&ba->BP, &rb->RenderDataPool, &rb->InitialBoundingAreas[(row + 1) * 4 + col]);
+                       }
+                       if (col != sp_w - 1) {
+                               list_append_pointer_static(&ba->RP, &rb->RenderDataPool, &rb->InitialBoundingAreas[row * 4 + col + 1]);
+                       }
+               }
+       }
+}
+void lanpr_connect_new_bounding_areas(LANPR_RenderBuffer *rb, LANPR_BoundingArea *Root) {
+       LANPR_BoundingArea *ba = Root->Child, *tba;
+       nListItemPointer *lip, *lip2, *next_lip;
+       nStaticMemoryPool *mph = &rb->RenderDataPool;
+
+       list_append_pointer_static_pool(mph, &ba[1].RP, &ba[0]);
+       list_append_pointer_static_pool(mph, &ba[0].LP, &ba[1]);
+       list_append_pointer_static_pool(mph, &ba[1].BP, &ba[2]);
+       list_append_pointer_static_pool(mph, &ba[2].UP, &ba[1]);
+       list_append_pointer_static_pool(mph, &ba[2].RP, &ba[3]);
+       list_append_pointer_static_pool(mph, &ba[3].LP, &ba[2]);
+       list_append_pointer_static_pool(mph, &ba[3].UP, &ba[0]);
+       list_append_pointer_static_pool(mph, &ba[0].BP, &ba[3]);
+
+       for (lip = Root->LP.first; lip; lip = lip->pNext) {
+               tba = lip->p;
+               if (ba[1].U > tba->B && ba[1].B < tba->U) { list_append_pointer_static_pool(mph, &ba[1].LP, tba); list_append_pointer_static_pool(mph, &tba->RP, &ba[1]); }
+               if (ba[2].U > tba->B && ba[2].B < tba->U) { list_append_pointer_static_pool(mph, &ba[2].LP, tba); list_append_pointer_static_pool(mph, &tba->RP, &ba[2]); }
+       }
+       for (lip = Root->RP.first; lip; lip = lip->pNext) {
+               tba = lip->p;
+               if (ba[0].U > tba->B && ba[0].B < tba->U) { list_append_pointer_static_pool(mph, &ba[0].RP, tba); list_append_pointer_static_pool(mph, &tba->LP, &ba[0]); }
+               if (ba[3].U > tba->B && ba[3].B < tba->U) { list_append_pointer_static_pool(mph, &ba[3].RP, tba); list_append_pointer_static_pool(mph, &tba->LP, &ba[3]); }
+       }
+       for (lip = Root->UP.first; lip; lip = lip->pNext) {
+               tba = lip->p;
+               if (ba[0].R > tba->L && ba[0].L < tba->R) { list_append_pointer_static_pool(mph, &ba[0].UP, tba); list_append_pointer_static_pool(mph, &tba->BP, &ba[0]); }
+               if (ba[1].R > tba->L && ba[1].L < tba->R) { list_append_pointer_static_pool(mph, &ba[1].UP, tba); list_append_pointer_static_pool(mph, &tba->BP, &ba[1]); }
+       }
+       for (lip = Root->BP.first; lip; lip = lip->pNext) {
+               tba = lip->p;
+               if (ba[2].R > tba->L && ba[2].L < tba->R) { list_append_pointer_static_pool(mph, &ba[2].BP, tba); list_append_pointer_static_pool(mph, &tba->UP, &ba[2]); }
+               if (ba[3].R > tba->L && ba[3].L < tba->R) { list_append_pointer_static_pool(mph, &ba[3].BP, tba); list_append_pointer_static_pool(mph, &tba->UP, &ba[3]); }
+       }
+       for (lip = Root->LP.first; lip; lip = lip->pNext) {
+               for (lip2 = ((LANPR_BoundingArea *)lip->p)->RP.first; lip2; lip2 = next_lip) {
+                       next_lip = lip2->pNext;
+                       tba = lip2->p;
+                       if (tba == Root) {
+                               list_remove_pointer_item_no_free(&((LANPR_BoundingArea *)lip->p)->RP, lip2);
+                               if (ba[1].U > tba->B && ba[1].B < tba->U) list_append_pointer_static_pool(mph, &tba->RP, &ba[1]);
+                               if (ba[2].U > tba->B && ba[2].B < tba->U) list_append_pointer_static_pool(mph, &tba->RP, &ba[2]);
+                       }
+               }
+       }
+       for (lip = Root->RP.first; lip; lip = lip->pNext) {
+               for (lip2 = ((LANPR_BoundingArea *)lip->p)->LP.first; lip2; lip2 = next_lip) {
+                       next_lip = lip2->pNext;
+                       tba = lip2->p;
+                       if (tba == Root) {
+                               list_remove_pointer_item_no_free(&((LANPR_BoundingArea *)lip->p)->LP, lip2);
+                               if (ba[0].U > tba->B && ba[0].B < tba->U) list_append_pointer_static_pool(mph, &tba->LP, &ba[0]);
+                               if (ba[3].U > tba->B && ba[3].B < tba->U) list_append_pointer_static_pool(mph, &tba->LP, &ba[3]);
+                       }
+               }
+       }
+       for (lip = Root->UP.first; lip; lip = lip->pNext) {
+               for (lip2 = ((LANPR_BoundingArea *)lip->p)->BP.first; lip2; lip2 = next_lip) {
+                       next_lip = lip2->pNext;
+                       tba = lip2->p;
+                       if (tba == Root) {
+                               list_remove_pointer_item_no_free(&((LANPR_BoundingArea *)lip->p)->BP, lip2);
+                               if (ba[0].R > tba->L && ba[0].L < tba->R) list_append_pointer_static_pool(mph, &tba->UP, &ba[0]);
+                               if (ba[1].R > tba->L && ba[1].L < tba->R) list_append_pointer_static_pool(mph, &tba->UP, &ba[1]);
+                       }
+               }
+       }
+       for (lip = Root->BP.first; lip; lip = lip->pNext) {
+               for (lip2 = ((LANPR_BoundingArea *)lip->p)->UP.first; lip2; lip2 = next_lip) {
+                       next_lip = lip2->pNext;
+                       tba = lip2->p;
+                       if (tba == Root) {
+                               list_remove_pointer_item_no_free(&((LANPR_BoundingArea *)lip->p)->UP, lip2);
+                               if (ba[2].R > tba->L && ba[2].L < tba->R) list_append_pointer_static_pool(mph, &tba->BP, &ba[2]);
+                               if (ba[3].R > tba->L && ba[3].L < tba->R) list_append_pointer_static_pool(mph, &tba->BP, &ba[3]);
+                       }
+               }
+       }
+       while (list_pop_pointer_no_free(&Root->LP));
+       while (list_pop_pointer_no_free(&Root->RP));
+       while (list_pop_pointer_no_free(&Root->UP));
+       while (list_pop_pointer_no_free(&Root->BP));
+}
+void lanpr_link_triangle_with_bounding_area(LANPR_RenderBuffer *rb, LANPR_BoundingArea *RootBoundingArea, LANPR_RenderTriangle *rt, real *LRUB, int Recursive);
+void lanpr_triangle_enable_intersections_in_bounding_area(LANPR_RenderBuffer *rb, LANPR_RenderTriangle *rt, LANPR_BoundingArea *ba);
+
+void lanpr_split_bounding_area(LANPR_RenderBuffer *rb, LANPR_BoundingArea *Root) {
+       LANPR_BoundingArea *ba = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_BoundingArea) * 4);
+       LANPR_RenderTriangle *rt;
+
+       ba[0].L = Root->CX;
+       ba[0].R = Root->R;
+       ba[0].U = Root->U;
+       ba[0].B = Root->CY;
+       ba[0].CX = (ba[0].L + ba[0].R) / 2;
+       ba[0].CY = (ba[0].U + ba[0].B) / 2;
+
+       ba[1].L = Root->L;
+       ba[1].R = Root->CX;
+       ba[1].U = Root->U;
+       ba[1].B = Root->CY;
+       ba[1].CX = (ba[1].L + ba[1].R) / 2;
+       ba[1].CY = (ba[1].U + ba[1].B) / 2;
+
+       ba[2].L = Root->L;
+       ba[2].R = Root->CX;
+       ba[2].U = Root->CY;
+       ba[2].B = Root->B;
+       ba[2].CX = (ba[2].L + ba[2].R) / 2;
+       ba[2].CY = (ba[2].U + ba[2].B) / 2;
+
+       ba[3].L = Root->CX;
+       ba[3].R = Root->R;
+       ba[3].U = Root->CY;
+       ba[3].B = Root->B;
+       ba[3].CX = (ba[3].L + ba[3].R) / 2;
+       ba[3].CY = (ba[3].U + ba[3].B) / 2;
+
+       Root->Child = ba;
+
+       lanpr_connect_new_bounding_areas(rb, Root);
+
+       while (rt = list_pop_pointer_no_free(&Root->LinkedTriangles)) {
+               LANPR_BoundingArea *ba = Root->Child;
+               real B[4];
+               B[0] = MIN3(rt->V[0]->FrameBufferCoord[0], rt->V[1]->FrameBufferCoord[0], rt->V[2]->FrameBufferCoord[0]);
+               B[1] = MAX3(rt->V[0]->FrameBufferCoord[0], rt->V[1]->FrameBufferCoord[0], rt->V[2]->FrameBufferCoord[0]);
+               B[2] = MAX3(rt->V[0]->FrameBufferCoord[1], rt->V[1]->FrameBufferCoord[1], rt->V[2]->FrameBufferCoord[1]);
+               B[3] = MIN3(rt->V[0]->FrameBufferCoord[1], rt->V[1]->FrameBufferCoord[1], rt->V[2]->FrameBufferCoord[1]);
+               if (TNS_BOUND_AREA_CROSSES(B, &ba[0].L)) lanpr_link_triangle_with_bounding_area(rb, &ba[0], rt, B, 0);
+               if (TNS_BOUND_AREA_CROSSES(B, &ba[1].L)) lanpr_link_triangle_with_bounding_area(rb, &ba[1], rt, B, 0);
+               if (TNS_BOUND_AREA_CROSSES(B, &ba[2].L)) lanpr_link_triangle_with_bounding_area(rb, &ba[2], rt, B, 0);
+               if (TNS_BOUND_AREA_CROSSES(B, &ba[3].L)) lanpr_link_triangle_with_bounding_area(rb, &ba[3], rt, B, 0);
+       }
+
+       rb->BoundingAreaCount += 3;
+}
+int lanpr_line_crosses_bounding_area(LANPR_RenderBuffer *fb, tnsVector2d L, tnsVector2d R, LANPR_BoundingArea *ba) {
+       real vx, vy;
+       tnsVector4d converted;
+       real c1, c;
+
+       if ((converted[0] = (real)ba->L) > MAX2(L[0], R[0])) return 0;
+       if ((converted[1] = (real)ba->R) < MIN2(L[0], R[0])) return 0;
+       if ((converted[2] = (real)ba->B) > MAX2(L[1], R[1])) return 0;
+       if ((converted[3] = (real)ba->U) < MIN2(L[1], R[1])) return 0;
+
+       vx = L[0] - R[0];
+       vy = L[1] - R[1];
+
+       c1 = vx * (converted[2] - L[1]) - vy * (converted[0] - L[0]);
+       c = c1;
+
+       c1 = vx * (converted[2] - L[1]) - vy * (converted[1] - L[0]);
+       if (c1 * c <= 0) return 1;
+       else c = c1;
+
+       c1 = vx * (converted[3] - L[1]) - vy * (converted[0] - L[0]);
+       if (c1 * c <= 0) return 1;
+       else c = c1;
+
+       c1 = vx * (converted[3] - L[1]) - vy * (converted[1] - L[0]);
+       if (c1 * c <= 0) return 1;
+       else c = c1;
+
+       return 0;
+}
+int lanpr_triangle_covers_bounding_area(LANPR_RenderBuffer *fb, LANPR_RenderTriangle *rt, LANPR_BoundingArea *ba) {
+       tnsVector2d p1, p2, p3, p4;
+       real
+       *FBC1 = rt->V[0]->FrameBufferCoord,
+       *FBC2 = rt->V[1]->FrameBufferCoord,
+       *FBC3 = rt->V[2]->FrameBufferCoord;
+
+       p3[0] = p1[0] = (real)ba->L;
+       p2[1] = p1[1] = (real)ba->B;
+       p2[0] = p4[0] = (real)ba->R;
+       p3[1] = p4[1] = (real)ba->U;
+
+       if (FBC1[0] >= p1[0] && FBC1[0] <= p2[0] && FBC1[1] >= p1[1] && FBC1[1] <= p3[1]) return 1;
+       if (FBC2[0] >= p1[0] && FBC2[0] <= p2[0] && FBC2[1] >= p1[1] && FBC2[1] <= p3[1]) return 1;
+       if (FBC3[0] >= p1[0] && FBC3[0] <= p2[0] && FBC3[1] >= p1[1] && FBC3[1] <= p3[1]) return 1;
+
+       if (lanpr_point_inside_triangled(p1, FBC1, FBC2, FBC3) ||
+           lanpr_point_inside_triangled(p2, FBC1, FBC2, FBC3) ||
+           lanpr_point_inside_triangled(p3, FBC1, FBC2, FBC3) ||
+           lanpr_point_inside_triangled(p4, FBC1, FBC2, FBC3)) return 1;
+
+       if  (lanpr_line_crosses_bounding_area(fb, FBC1, FBC2, ba)) return 1;
+       elif(lanpr_line_crosses_bounding_area(fb, FBC2, FBC3, ba)) return 1;
+       elif(lanpr_line_crosses_bounding_area(fb, FBC3, FBC1, ba)) return 1;
+
+       return 0;
+}
+void lanpr_link_triangle_with_bounding_area(LANPR_RenderBuffer *rb, LANPR_BoundingArea *RootBoundingArea, LANPR_RenderTriangle *rt, real *LRUB, int Recursive) {
+       if (!lanpr_triangle_covers_bounding_area(rb, rt, RootBoundingArea)) return;
+       if (!RootBoundingArea->Child) {
+               list_append_pointer_static_pool(&rb->RenderDataPool, &RootBoundingArea->LinkedTriangles, rt);
+               RootBoundingArea->TriangleCount++;
+               if (RootBoundingArea->TriangleCount > 200 && Recursive) {
+                       lanpr_split_bounding_area(rb, RootBoundingArea);
+               }
+               if (Recursive && rb->enable_intersections) lanpr_triangle_enable_intersections_in_bounding_area(rb, rt, RootBoundingArea);
+       }
+       else {
+               LANPR_BoundingArea *ba = RootBoundingArea->Child;
+               real *B1 = LRUB;
+               real B[4];
+               if (!LRUB) {
+                       B[0] = MIN3(rt->V[0]->FrameBufferCoord[0], rt->V[1]->FrameBufferCoord[0], rt->V[2]->FrameBufferCoord[0]);
+                       B[1] = MAX3(rt->V[0]->FrameBufferCoord[0], rt->V[1]->FrameBufferCoord[0], rt->V[2]->FrameBufferCoord[0]);
+                       B[2] = MAX3(rt->V[0]->FrameBufferCoord[1], rt->V[1]->FrameBufferCoord[1], rt->V[2]->FrameBufferCoord[1]);
+                       B[3] = MIN3(rt->V[0]->FrameBufferCoord[1], rt->V[1]->FrameBufferCoord[1], rt->V[2]->FrameBufferCoord[1]);
+                       B1 = B;
+               }
+               if (TNS_BOUND_AREA_CROSSES(B1, &ba[0].L)) lanpr_link_triangle_with_bounding_area(rb, &ba[0], rt, B1, Recursive);
+               if (TNS_BOUND_AREA_CROSSES(B1, &ba[1].L)) lanpr_link_triangle_with_bounding_area(rb, &ba[1], rt, B1, Recursive);
+               if (TNS_BOUND_AREA_CROSSES(B1, &ba[2].L)) lanpr_link_triangle_with_bounding_area(rb, &ba[2], rt, B1, Recursive);
+               if (TNS_BOUND_AREA_CROSSES(B1, &ba[3].L)) lanpr_link_triangle_with_bounding_area(rb, &ba[3], rt, B1, Recursive);
+       }
+}
+void lanpr_link_line_with_bounding_area(LANPR_RenderBuffer *rb, LANPR_BoundingArea *RootBoundingArea, LANPR_RenderLine *rl) {
+       list_append_pointer_static_pool(&rb->RenderDataPool, &RootBoundingArea->LinkedLines, rl);
+}
+int lanpr_get_triangle_bounding_areas(LANPR_RenderBuffer *rb, LANPR_RenderTriangle *rt, int *rowBegin, int *rowEnd, int *colBegin, int *colEnd) {
+       real sp_w = rb->WidthPerTile, sp_h = rb->HeightPerTile;
+       real B[4];
+
+       if (!rt->V[0] || !rt->V[1] || !rt->V[2]) return 0;
+
+       B[0] = MIN3(rt->V[0]->FrameBufferCoord[0], rt->V[1]->FrameBufferCoord[0], rt->V[2]->FrameBufferCoord[0]);
+       B[1] = MAX3(rt->V[0]->FrameBufferCoord[0], rt->V[1]->FrameBufferCoord[0], rt->V[2]->FrameBufferCoord[0]);
+       B[2] = MIN3(rt->V[0]->FrameBufferCoord[1], rt->V[1]->FrameBufferCoord[1], rt->V[2]->FrameBufferCoord[1]);
+       B[3] = MAX3(rt->V[0]->FrameBufferCoord[1], rt->V[1]->FrameBufferCoord[1], rt->V[2]->FrameBufferCoord[1]);
+
+       if (B[0] > 1 || B[1] < -1 || B[2] > 1 || B[3] < -1) return 0;
+
+       (*colBegin) = (int)((B[0] + 1.0) / sp_w);
+       (*colEnd) = (int)((B[1] + 1.0) / sp_w);
+       (*rowEnd) = rb->TileCountY - (int)((B[2] + 1.0) / sp_h) - 1;
+       (*rowBegin) = rb->TileCountY - (int)((B[3] + 1.0) / sp_h) - 1;
+
+       if ((*colEnd) >= rb->TileCountX) (*colEnd) = rb->TileCountX - 1;
+       if ((*rowEnd) >= rb->TileCountY) (*rowEnd) = rb->TileCountY - 1;
+       if ((*colBegin) < 0) (*colBegin) = 0;
+       if ((*rowBegin) < 0) (*rowBegin) = 0;
+
+       return 1;
+}
+int lanpr_get_line_bounding_areas(LANPR_RenderBuffer *rb, LANPR_RenderLine *rl, int *rowBegin, int *rowEnd, int *colBegin, int *colEnd) {
+       real sp_w = rb->WidthPerTile, sp_h = rb->HeightPerTile;
+       real B[4];
+
+       if (!rl->L || !rl->R) return 0;
+
+       if (rl->L->FrameBufferCoord[0] != rl->L->FrameBufferCoord[0] || rl->R->FrameBufferCoord[0] != rl->R->FrameBufferCoord[0]) return 0;
+
+       B[0] = MIN2(rl->L->FrameBufferCoord[0], rl->R->FrameBufferCoord[0]);
+       B[1] = MAX2(rl->L->FrameBufferCoord[0], rl->R->FrameBufferCoord[0]);
+       B[2] = MIN2(rl->L->FrameBufferCoord[1], rl->R->FrameBufferCoord[1]);
+       B[3] = MAX2(rl->L->FrameBufferCoord[1], rl->R->FrameBufferCoord[1]);
+
+       if (B[0] > 1 || B[1] < -1 || B[2] > 1 || B[3] < -1) return 0;
+
+       (*colBegin) = (int)((B[0] + 1.0) / sp_w);
+       (*colEnd) = (int)((B[1] + 1.0) / sp_w);
+       (*rowEnd) = rb->TileCountY - (int)((B[2] + 1.0) / sp_h) - 1;
+       (*rowBegin) = rb->TileCountY - (int)((B[3] + 1.0) / sp_h) - 1;
+
+       if ((*colEnd) >= rb->TileCountX) (*colEnd) = rb->TileCountX - 1;
+       if ((*rowEnd) >= rb->TileCountY) (*rowEnd) = rb->TileCountY - 1;
+       if ((*colBegin) < 0) (*colBegin) = 0;
+       if ((*rowBegin) < 0) (*rowBegin) = 0;
+
+       return 1;
+}
+LANPR_BoundingArea *lanpr_get_point_bounding_area(LANPR_RenderBuffer *rb, real x, real y) {
+       real sp_w = rb->WidthPerTile, sp_h = rb->HeightPerTile;
+       int col, row;
+
+       if (x > 1 || x < -1 || y > 1 || y < -1) return 0;
+
+       col = (int)((x + 1.0) / sp_w);
+       row = rb->TileCountY - (int)((y + 1.0) / sp_h) - 1;
+
+       if (col >= rb->TileCountX) col = rb->TileCountX - 1;
+       if (row >= rb->TileCountY) row = rb->TileCountY - 1;
+       if (col < 0) col = 0;
+       if (row < 0) row = 0;
+
+       return &rb->InitialBoundingAreas[row * 4 + col];
+}
+void lanpr_add_triangles(LANPR_RenderBuffer *rb) {
+       LANPR_RenderElementLinkNode *reln;
+       LANPR_RenderTriangle *rt;
+       //tnsMatrix44d VP;
+       Camera *c = ((Camera *)rb->Scene->camera);
+       int i, lim;
+       int x1, x2, y1, y2;
+       int r, co;
+       //tnsMatrix44d proj, view, result, inv;
+       //tmat_make_perspective_matrix_44d(proj, c->FOV, (real)fb->W / (real)fb->H, c->clipsta, c->clipend);
+       //tmat_load_identity_44d(view);
+       //tObjApplyself_transformMatrix(c, 0);
+       //tObjApplyGlobalTransformMatrixReverted(c);
+       //tmat_inverse_44d(inv, c->Base.GlobalTransform);
+       //tmat_multiply_44d(result, proj, inv);
+       //memcpy(proj, result, sizeof(tnsMatrix44d));
+
+       //tnsglobal_TriangleIntersectionCount = 0;
+
+       //tnsset_RenderOverallProgress(rb, NUL_MH2);
+       rb->CalculationStatus = TNS_CALCULATION_INTERSECTION;
+       //nulThreadNotifyUsers("tns.render_buffer_list.calculation_status");
+
+       for (reln = rb->TriangleBufferPointers.first; reln; reln = reln->Item.pNext) {
+               rt = reln->Pointer;
+               lim = reln->ElementCount;
+               for (i = 0; i < lim; i++) {
+                       if (rt->CullStatus) {
+                               rt = (void *)(((BYTE *)rt) + rb->TriangleSize); continue;
+                       }
+                       if (lanpr_get_triangle_bounding_areas(rb, rt, &y1, &y2, &x1, &x2)) {
+                               for (co = x1; co <= x2; co++) {
+                                       for (r = y1; r <= y2; r++) {
+                                               lanpr_link_triangle_with_bounding_area(rb, &rb->InitialBoundingAreas[r * 4 + co], rt, 0, 1);
+                                       }
+                               }
+                       }
+                       else {
+                               ;//throw away.
+                       }
+                       rt = (void *)(((BYTE *)rt) + rb->TriangleSize);
+                       //if (tnsglobal_TriangleIntersectionCount >= 2000) {
+                       //tnsset_PlusRenderIntersectionCount(rb, tnsglobal_TriangleIntersectionCount);
+                       //tnsglobal_TriangleIntersectionCount = 0;
+                       //}
+               }
+       }
+       //tnsset_PlusRenderIntersectionCount(rb, tnsglobal_TriangleIntersectionCount);
+}
+LANPR_BoundingArea *lanpr_get_next_bounding_area(LANPR_BoundingArea *This, LANPR_RenderLine *rl, real x, real y, real k, int PositiveX, int PositiveY, real *NextX, real *NextY) {
+       real rx, ry, ux, uy, lx, ly, bx, by;
+       real r1, r2;
+       LANPR_BoundingArea *ba; nListItemPointer *lip;
+       if (PositiveX > 0) {
+               rx = This->R;
+               ry = y + k * (rx - x);
+               if (PositiveY > 0) {
+                       uy = This->U;
+                       ux = x + (uy - y) / k;
+                       r1 = tMatGetLinearRatio(rl->L->FrameBufferCoord[0], rl->R->FrameBufferCoord[0], rx);
+                       r2 = tMatGetLinearRatio(rl->L->FrameBufferCoord[0], rl->R->FrameBufferCoord[0], ux);
+                       if (MIN2(r1, r2) > 1) return 0;
+                       if (r1 <= r2) {
+                               for (lip = This->RP.first; lip; lip = lip->pNext) {
+                                       ba = lip->p;
+                                       if (ba->U >= ry && ba->B < ry) { *NextX = rx; *NextY = ry; return ba; }
+                               }
+                       }
+                       else {
+                               for (lip = This->UP.first; lip; lip = lip->pNext) {
+                                       ba = lip->p;
+                                       if (ba->R >= ux && ba->L < ux) { *NextX = ux; *NextY = uy; return ba; }
+                               }
+                       }
+               }
+               else if (PositiveY < 0) {
+                       by = This->B;
+                       bx = x + (by - y) / k;
+                       r1 = tMatGetLinearRatio(rl->L->FrameBufferCoord[0], rl->R->FrameBufferCoord[0], rx);
+                       r2 = tMatGetLinearRatio(rl->L->FrameBufferCoord[0], rl->R->FrameBufferCoord[0], bx);
+                       if (MIN2(r1, r2) > 1) return 0;
+                       if (r1 <= r2) {
+                               for (lip = This->RP.first; lip; lip = lip->pNext) {
+                                       ba = lip->p;
+                                       if (ba->U >= ry && ba->B < ry) { *NextX = rx; *NextY = ry; return ba; }
+                               }
+                       }
+                       else {
+                               for (lip = This->BP.first; lip; lip = lip->pNext) {
+                                       ba = lip->p;
+                                       if (ba->R >= bx && ba->L < bx) { *NextX = bx; *NextY = by; return ba; }
+                               }
+                       }
+               }else { // Y diffence == 0
+                       r1 = tMatGetLinearRatio(rl->L->FrameBufferCoord[0], rl->R->FrameBufferCoord[0], This->R);
+                       if (r1 > 1) return 0;
+                       for (lip = This->RP.first; lip; lip = lip->pNext) {
+                               ba = lip->p;
+                               if (ba->U >= y && ba->B < y) { *NextX = This->R; *NextY = y; return ba; }
+                       }
+               }
+       }else if (PositiveX < 0) { // X diffence < 0
+               lx = This->L;
+               ly = y + k * (lx - x);
+               if (PositiveY > 0) {
+                       uy = This->U;
+                       ux = x + (uy - y) / k;
+                       r1 = tMatGetLinearRatio(rl->L->FrameBufferCoord[0], rl->R->FrameBufferCoord[0], lx);
+                       r2 = tMatGetLinearRatio(rl->L->FrameBufferCoord[0], rl->R->FrameBufferCoord[0], ux);
+                       if (MIN2(r1, r2) > 1) return 0;
+                       if (r1 <= r2) {
+                               for (lip = This->LP.first; lip; lip = lip->pNext) {
+                                       ba = lip->p;
+                                       if (ba->U >= ly && ba->B < ly) { *NextX = lx; *NextY = ly; return ba; }
+                               }
+                       }
+                       else {
+                               for (lip = This->UP.first; lip; lip = lip->pNext) {
+                                       ba = lip->p;
+                                       if (ba->R >= ux && ba->L < ux) { *NextX = ux; *NextY = uy; return ba; }
+                               }
+                       }
+               }
+               else if (PositiveY < 0) {
+                       by = This->B;
+                       bx = x + (by - y) / k;
+                       r1 = tMatGetLinearRatio(rl->L->FrameBufferCoord[0], rl->R->FrameBufferCoord[0], lx);
+                       r2 = tMatGetLinearRatio(rl->L->FrameBufferCoord[0], rl->R->FrameBufferCoord[0], bx);
+                       if (MIN2(r1, r2) > 1) return 0;
+                       if (r1 <= r2) {
+                               for (lip = This->LP.first; lip; lip = lip->pNext) {
+                                       ba = lip->p;
+                                       if (ba->U >= ly && ba->B < ly) { *NextX = lx; *NextY = ly; return ba; }
+                               }
+                       }
+                       else {
+                               for (lip = This->BP.first; lip; lip = lip->pNext) {
+                                       ba = lip->p;
+                                       if (ba->R >= bx && ba->L < bx) { *NextX = bx; *NextY = by; return ba; }
+                               }
+                       }
+               }else { // Y diffence == 0
+                       r1 = tMatGetLinearRatio(rl->L->FrameBufferCoord[0], rl->R->FrameBufferCoord[0], This->L);
+                       if (r1 > 1) return 0;
+                       for (lip = This->LP.first; lip; lip = lip->pNext) {
+                               ba = lip->p;
+                               if (ba->U >= y && ba->B < y) { *NextX = This->L; *NextY = y; return ba; }
+                       }
+               }
+       }else { // X difference == 0;
+               if (PositiveY > 0) {
+                       r1 = tMatGetLinearRatio(rl->L->FrameBufferCoord[1], rl->R->FrameBufferCoord[1], This->U);
+                       if (r1 > 1) return 0;
+                       for (lip = This->UP.first; lip; lip = lip->pNext) {
+                               ba = lip->p;
+                               if (ba->R > x && ba->L <= x) { *NextX = x; *NextY = This->U; return ba; }
+                       }
+               }
+               else if (PositiveY < 0) {
+                       r1 = tMatGetLinearRatio(rl->L->FrameBufferCoord[1], rl->R->FrameBufferCoord[1], This->B);
+                       if (r1 > 1) return 0;
+                       for (lip = This->BP.first; lip; lip = lip->pNext) {
+                               ba = lip->p;
+                               if (ba->R > x && ba->L <= x) { *NextX = x; *NextY = This->B; return ba; }
+                       }
+               }
+               else return 0; // segment has no length
+       }
+       return 0;
+}
+
+LANPR_BoundingArea *lanpr_get_bounding_area(LANPR_RenderBuffer *rb, real x, real y) {
+       LANPR_BoundingArea *iba;
+       real sp_w = rb->WidthPerTile, sp_h = rb->HeightPerTile;
+       int c = (int)((x + 1.0) / sp_w);
+       int r = rb->TileCountY - (int)((y + 1.0) / sp_h) - 1;
+       if (r < 0) r = 0;
+       if (c < 0) c = 0;
+       if (r >= rb->TileCountY) r = rb->TileCountY - 1;
+       if (c >= rb->TileCountX) c = rb->TileCountX - 1;
+
+       iba = &rb->InitialBoundingAreas[r * 4 + c];
+       while (iba->Child) {
+               if (x > iba->CX) {
+                       if (y > iba->CY) iba = &iba->Child[0];
+                       else iba = &iba->Child[3];
+               }
+               else {
+                       if (y > iba->CY) iba = &iba->Child[1];
+                       else iba = &iba->Child[2];
+               }
+       }
+       return iba;
+}
+LANPR_BoundingArea *lanpr_get_first_possible_bounding_area(LANPR_RenderBuffer *rb, LANPR_RenderLine *rl) {
+       LANPR_BoundingArea *iba;
+       real p[2] = { rl->L->FrameBufferCoord[0], rl->L->FrameBufferCoord[1] };
+       tnsVector2d LU = { -1, 1 }, RU = { 1, 1 }, LB = { -1, -1 }, RB = { 1, -1 };
+       real r = 1, sr = 1;
+
+       if (p[0] > -1 && p[0] < 1 && p[1] > -1 && p[1] < 1) {
+               return lanpr_get_bounding_area(rb, p[0], p[1]);
+       }
+       else {
+               if (lanpr_LineIntersectTest2d(rl->L->FrameBufferCoord, rl->R->FrameBufferCoord, LU, RU, &sr) && sr < r && sr > 0) r = sr;
+               if (lanpr_LineIntersectTest2d(rl->L->FrameBufferCoord, rl->R->FrameBufferCoord, LB, RB, &sr) && sr < r && sr > 0) r = sr;
+               if (lanpr_LineIntersectTest2d(rl->L->FrameBufferCoord, rl->R->FrameBufferCoord, LB, LU, &sr) && sr < r && sr > 0) r = sr;
+               if (lanpr_LineIntersectTest2d(rl->L->FrameBufferCoord, rl->R->FrameBufferCoord, RB, RU, &sr) && sr < r && sr > 0) r = sr;
+               lanpr_LinearInterpolate2dv(rl->L->FrameBufferCoord, rl->R->FrameBufferCoord, r, p);
+
+               return lanpr_get_bounding_area(rb, p[0], p[1]);
+       }
+
+       real sp_w = rb->WidthPerTile, sp_h = rb->HeightPerTile;
+
+       return iba;
+}
+
+
+/* ======================================= geometry ============================================ */
+
+void lanpr_cut_render_line(LANPR_RenderBuffer *rb, LANPR_RenderLine *rl, real Begin, real End) {
+       LANPR_RenderLineSegment *rls = rl->Segments.first, *irls;
+       LANPR_RenderLineSegment *begin_segment = 0, *end_segment = 0;
+       LANPR_RenderLineSegment *ns = 0, *ns2 = 0;
+       int untouched = 0;
+
+       if (TNS_DOUBLE_CLOSE_ENOUGH(Begin, End)) return;
+
+       if (Begin != Begin)
+               Begin = 0;
+       if (End != End)
+               End = 0;
+
+       if (Begin > End) {
+               real t = Begin;
+               Begin = End;
+               End = t;
+       }
+
+       for (rls = rl->Segments.first; rls; rls = rls->Item.pNext) {
+               if (TNS_DOUBLE_CLOSE_ENOUGH(rls->at, Begin)) {
+                       begin_segment = rls;
+                       ns = begin_segment;
+                       break;
+               }
+               if (!rls->Item.pNext) {
+                       break;
+               }
+               irls = rls->Item.pNext;
+               if (irls->at > Begin + 1e-09 && Begin > rls->at) {
+                       begin_segment = irls;
+                       ns = mem_static_aquire_thread(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+                       break;
+               }
+       }
+       if (!begin_segment && TNS_DOUBLE_CLOSE_ENOUGH(1, End)) {
+               untouched = 1;
+       }
+       for (rls = begin_segment; rls; rls = rls->Item.pNext) {
+               if (TNS_DOUBLE_CLOSE_ENOUGH(rls->at, End)) {
+                       end_segment = rls;
+                       ns2 = end_segment;
+                       break;
+               }
+               //irls = rls->Item.pNext;
+               //added this to prevent rls->at == 1.0 (we don't need an end point for this)
+               if (!rls->Item.pNext && TNS_DOUBLE_CLOSE_ENOUGH(1, End)) {
+                       end_segment = rls;
+                       ns2 = end_segment;
+                       untouched = 1;
+                       break;
+               } elif(rls->at > End)
+               {
+                       end_segment = rls;
+                       ns2 = mem_static_aquire_thread(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+                       break;
+               }
+       }
+
+       if (!ns) ns = mem_static_aquire_thread(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+       if (!ns2) {
+               if (untouched) { ns2 = ns; end_segment = ns2; }
+               else ns2 = mem_static_aquire_thread(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+       }
+
+       if (begin_segment) {
+               if (begin_segment != ns) {
+                       ns->OcclusionLevel = begin_segment->Item.pPrev ? (irls = begin_segment->Item.pPrev)->OcclusionLevel : 0;
+                       list_insert_item_before(&rl->Segments, (void *)ns, (void *)begin_segment);
+               }
+       }
+       else {
+               ns->OcclusionLevel = (irls = rl->Segments.last)->OcclusionLevel;
+               BLI_addtail(&rl->Segments, ns);
+       }
+       if (end_segment) {
+               if (end_segment != ns2) {
+                       ns2->OcclusionLevel = end_segment->Item.pPrev ? (irls = end_segment->Item.pPrev)->OcclusionLevel : 0;
+                       list_insert_item_before(&rl->Segments, (void *)ns2, (void *)end_segment);
+               }
+       }
+       else {
+               ns2->OcclusionLevel = (irls = rl->Segments.last)->OcclusionLevel;
+               BLI_addtail(&rl->Segments, ns2);
+       }
+
+       ns->at = Begin;
+       if (!untouched) ns2->at = End;
+       else ns2 = ns2->Item.pNext;
+
+       for (rls = ns; rls && rls != ns2; rls = rls->Item.pNext) {
+               rls->OcclusionLevel++;
+       }
+}
+
+
+int lanpr_make_next_occlusion_task_info(LANPR_RenderBuffer *rb, LANPR_RenderTaskInfo *rti) {
+       nListItemPointer *p;
+       int i;
+       int res = 0;
+
+       BLI_spin_lock(&rb->csManagement);
+
+       if (rb->ContourManaged) {
+               p = rb->ContourManaged;
+               rti->Contour = (void *)p;
+               rti->ContourPointers.first = p;
+               for (i = 0; i < TNS_THREAD_LINE_COUNT && p; i++) {
+                       p = p->pNext;
+               }
+               rb->ContourManaged = p;
+               rti->ContourPointers.last = p ? p->pPrev : rb->Contours.last;
+               res = 1;
+       }
+       else {
+               list_handle_empty(&rti->ContourPointers);
+               rti->Contour = 0;
+       }
+
+       if (rb->IntersectionManaged) {
+               p = rb->IntersectionManaged;
+               rti->Intersection = (void *)p;
+               rti->IntersectionPointers.first = p;
+               for (i = 0; i < TNS_THREAD_LINE_COUNT && p; i++) {
+                       p = p->pNext;
+               }
+               rb->IntersectionManaged = p;
+               rti->IntersectionPointers.last = p ? p->pPrev : rb->IntersectionLines.last;
+               res = 1;
+       }
+       else {
+               list_handle_empty(&rti->IntersectionPointers);
+               rti->Intersection = 0;
+       }
+
+       if (rb->CreaseManaged) {
+               p = rb->CreaseManaged;
+               rti->Crease = (void *)p;
+               rti->CreasePointers.first = p;
+               for (i = 0; i < TNS_THREAD_LINE_COUNT && p; i++) {
+                       p = p->pNext;
+               }
+               rb->CreaseManaged = p;
+               rti->CreasePointers.last = p ? p->pPrev : rb->CreaseLines.last;
+               res = 1;
+       }
+       else {
+               list_handle_empty(&rti->CreasePointers);
+               rti->Crease = 0;
+       }
+
+       if (rb->MaterialManaged) {
+               p = rb->MaterialManaged;
+               rti->Material = (void *)p;
+               rti->MaterialPointers.first = p;
+               for (i = 0; i < TNS_THREAD_LINE_COUNT && p; i++) {
+                       p = p->pNext;
+               }
+               rb->MaterialManaged = p;
+               rti->MaterialPointers.last = p ? p->pPrev : rb->MaterialLines.last;
+               res = 1;
+       }
+       else {
+               list_handle_empty(&rti->MaterialPointers);
+               rti->Material = 0;
+       }
+
+       if (rb->EdgeMarkManaged) {
+               p = rb->EdgeMarkManaged;
+               rti->EdgeMark = (void *)p;
+               rti->EdgeMarkPointers.first = p;
+               for (i = 0; i < TNS_THREAD_LINE_COUNT && p; i++) {
+                       p = p->pNext;
+               }
+               rb->EdgeMarkManaged = p;
+               rti->EdgeMarkPointers.last = p ? p->pPrev : rb->EdgeMarks.last;
+               res = 1;
+       }
+       else {
+               list_handle_empty(&rti->EdgeMarkPointers);
+               rti->EdgeMark = 0;
+       }
+
+       BLI_spin_unlock(&rb->csManagement);
+
+       return res;
+}
+void lanpr_calculate_single_line_occlusion(LANPR_RenderBuffer *rb, LANPR_RenderLine *rl, int ThreadID) {
+       real x = rl->L->FrameBufferCoord[0], y = rl->L->FrameBufferCoord[1];
+       LANPR_BoundingArea *ba = lanpr_get_first_possible_bounding_area(rb, rl);
+       LANPR_BoundingArea *nba = ba;
+       LANPR_RenderTriangleThread *rt;
+       nListItemPointer *lip;
+       Object *c = rb->Scene->camera;
+       real l, r;
+       real k = (rl->R->FrameBufferCoord[1] - rl->L->FrameBufferCoord[1]) / (rl->R->FrameBufferCoord[0] - rl->L->FrameBufferCoord[0] + 1e-30);
+       int PositiveX = (rl->R->FrameBufferCoord[0] - rl->L->FrameBufferCoord[0]) > 0 ? 1 : (rl->R->FrameBufferCoord[0] == rl->L->FrameBufferCoord[0] ? 0 : -1);
+       int PositiveY = (rl->R->FrameBufferCoord[1] - rl->L->FrameBufferCoord[1]) > 0 ? 1 : (rl->R->FrameBufferCoord[1] == rl->L->FrameBufferCoord[1] ? 0 : -1);
+
+       //printf("PX %d %lf   PY %d %lf\n", PositiveX, rl->R->FrameBufferCoord[0] - rl->L->FrameBufferCoord[0], PositiveY, rl->R->FrameBufferCoord[1] - rl->L->FrameBufferCoord[1]);
+
+       while (nba) {
+
+
+               for (lip = nba->LinkedTriangles.first; lip; lip = lip->pNext) {
+                       rt = lip->p;
+                       if (rt->Testing[ThreadID] == rl || rl->L->IntersectWith == (void *)rt || rl->R->IntersectWith == (void *)rt) continue;
+                       rt->Testing[ThreadID] = rl;
+                       if (lanpr_triangle_line_imagespace_intersection_v2(&rb->csManagement, (void *)rt, rl, c, rb->ViewProjection, rb->ViewVector, &l, &r)) {
+                               lanpr_cut_render_line(rb, rl, l, r);
+                       }
+               }
+
+
+               nba = lanpr_get_next_bounding_area(nba, rl, x, y, k, PositiveX, PositiveY, &x, &y);
+       }
+}
+void lanpr_THREAD_calculate_line_occlusion(TaskPool *__restrict pool, LANPR_RenderTaskInfo *rti, int threadid) {
+       LANPR_RenderBuffer *rb = rti->RenderBuffer;
+       int ThreadId = rti->ThreadID;
+       nListItemPointer *lip;
+       int count = 0;
+
+       while (lanpr_make_next_occlusion_task_info(rb, rti)) {
+
+               for (lip = (void *)rti->Contour; lip && lip->pPrev != rti->ContourPointers.last; lip = lip->pNext) {
+                       lanpr_calculate_single_line_occlusion(rb, lip->p, rti->ThreadID);
+               }
+
+               for (lip = (void *)rti->Crease; lip && lip->pPrev != rti->CreasePointers.last; lip = lip->pNext) {
+                       lanpr_calculate_single_line_occlusion(rb, lip->p, rti->ThreadID);
+               }
+
+               for (lip = (void *)rti->Intersection; lip && lip->pPrev != rti->IntersectionPointers.last; lip = lip->pNext) {
+                       lanpr_calculate_single_line_occlusion(rb, lip->p, rti->ThreadID);
+               }
+
+               for (lip = (void *)rti->Material; lip && lip->pPrev != rti->MaterialPointers.last; lip = lip->pNext) {
+                       lanpr_calculate_single_line_occlusion(rb, lip->p, rti->ThreadID);
+               }
+
+               for (lip = (void *)rti->EdgeMark; lip && lip->pPrev != rti->EdgeMarkPointers.last; lip = lip->pNext) {
+                       lanpr_calculate_single_line_occlusion(rb, lip->p, rti->ThreadID);
+               }
+       }
+}
+void lanpr_THREAD_calculate_line_occlusion_begin(LANPR_RenderBuffer *rb) {
+       int ThreadCount = rb->ThreadCount;
+       LANPR_RenderTaskInfo *rti = MEM_callocN(sizeof(LANPR_RenderTaskInfo) * ThreadCount, "render task info");
+       TaskScheduler *scheduler = BLI_task_scheduler_get();
+       int i;
+
+       rb->ContourManaged = rb->Contours.first;
+       rb->CreaseManaged = rb->CreaseLines.first;
+       rb->IntersectionManaged = rb->IntersectionLines.first;
+       rb->MaterialManaged = rb->MaterialLines.first;
+       rb->EdgeMarkManaged = rb->EdgeMarks.first;
+
+       TaskPool *tp = BLI_task_pool_create(scheduler, 0);
+
+       for (i = 0; i < ThreadCount; i++) {
+               rti[i].ThreadID = i;
+               rti[i].RenderBuffer = rb;
+               BLI_task_pool_push(tp, lanpr_THREAD_calculate_line_occlusion, &rti[i], 0, TASK_PRIORITY_HIGH);
+       }
+       BLI_task_pool_work_and_wait(tp);
+
+       MEM_freeN(rti);
+}
+
+void lanpr_NO_THREAD_calculate_line_occlusion(LANPR_RenderBuffer *rb) {
+       nListItemPointer *lip;
+
+       for (lip = rb->Contours.first; lip; lip = lip->pNext) {
+               lanpr_calculate_single_line_occlusion(rb, lip->p, 0);
+       }
+
+       for (lip = rb->CreaseLines.first; lip; lip = lip->pNext) {
+               lanpr_calculate_single_line_occlusion(rb, lip->p, 0);
+       }
+
+       for (lip = rb->IntersectionLines.first; lip; lip = lip->pNext) {
+               lanpr_calculate_single_line_occlusion(rb, lip->p, 0);
+       }
+
+       for (lip = rb->MaterialLines.first; lip; lip = lip->pNext) {
+               lanpr_calculate_single_line_occlusion(rb, lip->p, 0);
+       }
+
+       for (lip = rb->EdgeMarks.first; lip; lip = lip->pNext) {
+               lanpr_calculate_single_line_occlusion(rb, lip->p, 0);
+       }
+}
+
+
+int lanpr_get_normal(tnsVector3d v1, tnsVector3d v2, tnsVector3d v3, tnsVector3d n, tnsVector3d Pos) {
+       tnsVector3d vec1, vec2;
+
+       tMatVectorMinus3d(vec1, v2, v1);
+       tMatVectorMinus3d(vec2, v3, v1);
+       tmat_vector_cross_3d(n, vec1, vec2);
+       tmat_normalize_self_3d(n);
+       if (Pos && (tmat_dot_3d(n, Pos, 1) < 0)) {
+               tMatVectorMultiSelf3d(n, -1.0f);
+               return 1;
+       }
+       return 0;
+}
+
+int lanpr_bound_box_crosses(tnsVector4d xxyy1, tnsVector4d xxyy2) {
+       real XMax1 = MAX2(xxyy1[0], xxyy1[1]);
+       real XMin1 = MIN2(xxyy1[0], xxyy1[1]);
+       real YMax1 = MAX2(xxyy1[2], xxyy1[3]);
+       real YMin1 = MIN2(xxyy1[2], xxyy1[3]);
+       real XMax2 = MAX2(xxyy2[0], xxyy2[1]);
+       real XMin2 = MIN2(xxyy2[0], xxyy2[1]);
+       real YMax2 = MAX2(xxyy2[2], xxyy2[3]);
+       real YMin2 = MIN2(xxyy2[2], xxyy2[3]);
+
+       if (XMax1 < XMin2 || XMin1 > XMax2) return 0;
+       if (YMax1 < YMin2 || YMin1 > YMax2) return 0;
+
+       return 1;
+}
+int lanpr_point_inside_triangled(tnsVector2d v, tnsVector2d v0, tnsVector2d v1, tnsVector2d v2) {
+       double cl, c;
+
+       cl = (v0[0] - v[0]) * (v1[1] - v[1]) - (v0[1] - v[1]) * (v1[0] - v[0]);
+       c = cl;
+
+       cl = (v1[0] - v[0]) * (v2[1] - v[1]) - (v1[1] - v[1]) * (v2[0] - v[0]);
+       if (c * cl <= 0) return 0;
+       else c = cl;
+
+       cl = (v2[0] - v[0]) * (v0[1] - v[1]) - (v2[1] - v[1]) * (v0[0] - v[0]);
+       if (c * cl <= 0) return 0;
+       else c = cl;
+
+       cl = (v0[0] - v[0]) * (v1[1] - v[1]) - (v0[1] - v[1]) * (v1[0] - v[0]);
+       if (c * cl <= 0) return 0;
+
+       return 1;
+}
+int lanpr_point_on_lined(tnsVector2d v, tnsVector2d v0, tnsVector2d v1) {
+       real c1, c2;
+
+       c1 = tMatGetLinearRatio(v0[0], v1[0], v[0]);
+       c2 = tMatGetLinearRatio(v0[1], v1[1], v[1]);
+
+       if (TNS_DOUBLE_CLOSE_ENOUGH(c1, c2) && c1 >= 0 && c1 <= 1) return 1;
+
+       return 0;
+}
+int lanpr_point_triangle_relation(tnsVector2d v, tnsVector2d v0, tnsVector2d v1, tnsVector2d v2) {
+       double cl, c;
+       real r;
+       if (lanpr_point_on_lined(v, v0, v1) || lanpr_point_on_lined(v, v1, v2) || lanpr_point_on_lined(v, v2, v0)) return 1;
+
+       cl = (v0[0] - v[0]) * (v1[1] - v[1]) - (v0[1] - v[1]) * (v1[0] - v[0]);
+       c = cl;
+
+       cl = (v1[0] - v[0]) * (v2[1] - v[1]) - (v1[1] - v[1]) * (v2[0] - v[0]);
+       if ((r = c * cl) < 0) return 0;
+       //elif(r == 0) return 1; // removed, point could still be on the extention line of some edge
+       else c = cl;
+
+       cl = (v2[0] - v[0]) * (v0[1] - v[1]) - (v2[1] - v[1]) * (v0[0] - v[0]);
+       if ((r = c * cl) < 0) return 0;
+       //elif(r == 0) return 1;
+       else c = cl;
+
+       cl = (v0[0] - v[0]) * (v1[1] - v[1]) - (v0[1] - v[1]) * (v1[0] - v[0]);
+       if ((r = c * cl) < 0) return 0;
+       elif(r == 0) return 1;
+
+       return 2;
+}
+int lanpr_point_inside_triangle3d(tnsVector3d v, tnsVector3d v0, tnsVector3d v1, tnsVector3d v2) {
+       tnsVector3d L, R;
+       tnsVector3d N1, N2;
+
+       tMatVectorMinus3d(L, v1, v0);
+       tMatVectorMinus3d(R, v, v1);
+       tmat_vector_cross_3d(N1, L, R);
+
+       tMatVectorMinus3d(L, v2, v1);
+       tMatVectorMinus3d(R, v, v2);
+       tmat_vector_cross_3d(N2, L, R);
+
+       if (tmat_dot_3d(N1, N2, 0) < 0) return 0;
+
+       tMatVectorMinus3d(L, v0, v2);
+       tMatVectorMinus3d(R, v, v0);
+       tmat_vector_cross_3d(N1, L, R);
+
+       if (tmat_dot_3d(N1, N2, 0) < 0) return 0;
+
+       tMatVectorMinus3d(L, v1, v0);
+       tMatVectorMinus3d(R, v, v1);
+       tmat_vector_cross_3d(N2, L, R);
+
+       if (tmat_dot_3d(N1, N2, 0) < 0) return 0;
+
+       return 1;
+}
+int lanpr_point_inside_triangle3de(tnsVector3d v, tnsVector3d v0, tnsVector3d v1, tnsVector3d v2) {
+       tnsVector3d L, R;
+       tnsVector3d N1, N2;
+       real d;
+
+       tMatVectorMinus3d(L, v1, v0);
+       tMatVectorMinus3d(R, v, v1);
+       //tmat_normalize_self_3d(L);
+       //tmat_normalize_self_3d(R);
+       tmat_vector_cross_3d(N1, L, R);
+
+       tMatVectorMinus3d(L, v2, v1);
+       tMatVectorMinus3d(R, v, v2);
+       //tmat_normalize_self_3d(L);
+       //tmat_normalize_self_3d(R);
+       tmat_vector_cross_3d(N2, L, R);
+
+       if ((d = tmat_dot_3d(N1, N2, 0)) < 0) return 0;
+       //if (d<DBL_EPSILON) return -1;
+
+       tMatVectorMinus3d(L, v0, v2);
+       tMatVectorMinus3d(R, v, v0);
+       //tmat_normalize_self_3d(L);
+       //tmat_normalize_self_3d(R);
+       tmat_vector_cross_3d(N1, L, R);
+
+       if ((d = tmat_dot_3d(N1, N2, 0)) < 0) return 0;
+       //if (d<DBL_EPSILON) return -1;
+
+       tMatVectorMinus3d(L, v1, v0);
+       tMatVectorMinus3d(R, v, v1);
+       //tmat_normalize_self_3d(L);
+       //tmat_normalize_self_3d(R);
+       tmat_vector_cross_3d(N2, L, R);
+
+       if ((d = tmat_dot_3d(N1, N2, 0)) < 0) return 0;
+       //if (d<DBL_EPSILON) return -1;
+
+       return 1;
+}
+
+LANPR_RenderElementLinkNode *lanpr_new_cull_triangle_space64(LANPR_RenderBuffer *rb) {
+       LANPR_RenderElementLinkNode *reln;
+
+       LANPR_RenderTriangle *RenderTriangles = MEM_callocN(64 * rb->TriangleSize, "render triangle space");//CreateNewBuffer(LANPR_RenderTriangle, 64);
+
+       reln = list_append_pointer_static_sized(&rb->TriangleBufferPointers, &rb->RenderDataPool, RenderTriangles,
+                                               sizeof(LANPR_RenderElementLinkNode));
+       reln->ElementCount = 64;
+       reln->Additional = 1;
+
+       return reln;
+}
+LANPR_RenderElementLinkNode *lanpr_new_cull_point_space64(LANPR_RenderBuffer *rb) {
+       LANPR_RenderElementLinkNode *reln;
+
+       LANPR_RenderVert *RenderVertices = MEM_callocN(sizeof(LANPR_RenderVert) * 64, "render vert space");//CreateNewBuffer(LANPR_RenderVert, 64);
+
+       reln = list_append_pointer_static_sized(&rb->VertexBufferPointers, &rb->RenderDataPool, RenderVertices,
+                                               sizeof(LANPR_RenderElementLinkNode));
+       reln->ElementCount = 64;
+       reln->Additional = 1;
+
+       return reln;
+}
+void lanpr_calculate_render_triangle_normal(LANPR_RenderTriangle *rt);
+void lanpr_assign_render_line_with_triangle(LANPR_RenderTriangle *rt) {
+       if (!rt->RL[0]->TL)
+               rt->RL[0]->TL = rt;
+       elif(!rt->RL[0]->TR)
+       rt->RL[0]->TR = rt;
+
+       if (!rt->RL[1]->TL)
+               rt->RL[1]->TL = rt;
+       elif(!rt->RL[1]->TR)
+       rt->RL[1]->TR = rt;
+
+       if (!rt->RL[2]->TL)
+               rt->RL[2]->TL = rt;
+       elif(!rt->RL[2]->TR)
+       rt->RL[2]->TR = rt;
+}
+void lanpr_post_triangle(LANPR_RenderTriangle *rt, LANPR_RenderTriangle *orig) {
+       if (rt->V[0]) tMatVectorAccum3d(rt->GC, rt->V[0]->FrameBufferCoord);
+       if (rt->V[1]) tMatVectorAccum3d(rt->GC, rt->V[1]->FrameBufferCoord);
+       if (rt->V[2]) tMatVectorAccum3d(rt->GC, rt->V[2]->FrameBufferCoord);
+       tMatVectorMultiSelf3d(rt->GC, 1.0f / 3.0f);
+
+       tMatVectorCopy3d(orig->GN, rt->GN);
+}
+
+#define RT_AT(head, rb, offset) \
+       ((BYTE *)head + offset * rb->TriangleSize)
+
+void lanpr_cull_triangles(LANPR_RenderBuffer *rb) {
+       LANPR_RenderLine *rl;
+       LANPR_RenderTriangle *rt, *rt1, *rt2;
+       LANPR_RenderVert *rv;
+       LANPR_RenderElementLinkNode *reln, *veln, *teln;
+       LANPR_RenderLineSegment *rls;
+       real *mv_inverse = rb->VPInverse;
+       real *vp = rb->ViewProjection;
+       int i;
+       real a;
+       int v_count = 0, t_count = 0;
+       Object *o;
+
+       real cam_pos[3];
+       Object* cam = ((Object *)rb->Scene->camera);
+       cam_pos[0] = cam->obmat[3][0];
+       cam_pos[1] = cam->obmat[3][1];
+       cam_pos[2] = cam->obmat[3][2];
+
+       real view_dir[3], clip_advance[3];
+       tMatVectorCopy3d(rb->ViewVector,view_dir);
+       tMatVectorCopy3d(rb->ViewVector,clip_advance);
+       tMatVectorMultiSelf3d(clip_advance, -((Camera*)cam->data)->clip_start);
+       tMatVectorAccum3d(cam_pos, clip_advance);
+
+       veln = lanpr_new_cull_point_space64(rb);
+       teln = lanpr_new_cull_triangle_space64(rb);
+       rv = &((LANPR_RenderVert *)veln->Pointer)[v_count];
+       rt1 = (void *)(((BYTE *)teln->Pointer) + rb->TriangleSize * t_count);
+
+       for (reln = rb->TriangleBufferPointers.first; reln; reln = reln->Item.pNext) {
+               i = 0;
+               if (reln->Additional) continue;
+               o = reln->ObjectRef;
+               for (i; i < reln->ElementCount; i++) {
+                       int In1 = 0, In2 = 0, In3 = 0;
+                       rt = (void *)(((BYTE *)reln->Pointer) + rb->TriangleSize * i);
+                       if (rt->V[0]->FrameBufferCoord[3] < 0) In1 = 1;
+                       if (rt->V[1]->FrameBufferCoord[3] < 0) In2 = 1;
+                       if (rt->V[2]->FrameBufferCoord[3] < 0) In3 = 1;
+
+                       rt->RL[0]->ObjectRef = o;
+                       rt->RL[1]->ObjectRef = o;
+                       rt->RL[2]->ObjectRef = o;
+
+                       if (v_count > 60) {
+                               veln->ElementCount = v_count;
+                               veln = lanpr_new_cull_point_space64(rb);
+                               v_count = 0;
+                       }
+
+                       if (t_count > 60) {
+                               teln->ElementCount = t_count;
+                               teln = lanpr_new_cull_triangle_space64(rb);
+                               t_count = 0;
+                       }
+
+                       //if ((!rt->RL[0]->Item.pNext && !rt->RL[0]->Item.pPrev) ||
+                       //    (!rt->RL[1]->Item.pNext && !rt->RL[1]->Item.pPrev) ||
+                       //    (!rt->RL[2]->Item.pNext && !rt->RL[2]->Item.pPrev)) {
+                       //      printf("'"); // means this triangle is lonely????
+                       //}
+
+                       rv = &((LANPR_RenderVert *)veln->Pointer)[v_count];
+                       rt1 = (void *)(((BYTE *)teln->Pointer) + rb->TriangleSize * t_count);
+                       rt2 = (void *)(((BYTE *)teln->Pointer) + rb->TriangleSize * (t_count + 1));
+
+                       real vv1[3], vv2[3], dot1, dot2;
+
+                       switch (In1 + In2 + In3) {
+                               case 0:
+                                       continue;
+                               case 3:
+                                       rt->CullStatus = TNS_CULL_DISCARD;
+                                       BLI_remlink(&rb->AllRenderLines, (void *)rt->RL[0]); rt->RL[0]->Item.pNext = rt->RL[0]->Item.pPrev = 0;
+                                       BLI_remlink(&rb->AllRenderLines, (void *)rt->RL[1]); rt->RL[1]->Item.pNext = rt->RL[1]->Item.pPrev = 0;
+                                       BLI_remlink(&rb->AllRenderLines, (void *)rt->RL[2]); rt->RL[2]->Item.pNext = rt->RL[2]->Item.pPrev = 0;
+                                       continue;
+                               case 2:
+                                       rt->CullStatus = TNS_CULL_USED;
+                                       if (!In1) {
+                                               tMatVectorMinus3d(vv1,rt->V[0]->GLocation,cam_pos);
+                                               tMatVectorMinus3d(vv2,cam_pos,rt->V[2]->GLocation);
+                                               dot1 = tmat_dot_3d(vv1,view_dir,0);
+                                               dot2 = tmat_dot_3d(vv2,view_dir,0);
+                                               a = dot1/(dot1+dot2);
+                                               rv[0].GLocation[0] = (1-a) * rt->V[0]->GLocation[0] + a * rt->V[2]->GLocation[0];
+                                               rv[0].GLocation[1] = (1-a) * rt->V[0]->GLocation[1] + a * rt->V[2]->GLocation[1];
+                                               rv[0].GLocation[2] = (1-a) * rt->V[0]->GLocation[2] + a * rt->V[2]->GLocation[2];
+                                               tmat_apply_transform_44d(rv[0].FrameBufferCoord,vp,rv[0].GLocation);
+
+                                               tMatVectorMinus3d(vv1,rt->V[0]->GLocation,cam_pos);
+                                               tMatVectorMinus3d(vv2,cam_pos,rt->V[1]->GLocation);
+                                               dot1 = tmat_dot_3d(vv1,view_dir,0);
+                                               dot2 = tmat_dot_3d(vv2,view_dir,0);
+                                               a = dot1/(dot1+dot2);
+                                               rv[1].GLocation[0] = (1-a) * rt->V[0]->GLocation[0] + a * rt->V[1]->GLocation[0];
+                                               rv[1].GLocation[1] = (1-a) * rt->V[0]->GLocation[1] + a * rt->V[1]->GLocation[1];
+                                               rv[1].GLocation[2] = (1-a) * rt->V[0]->GLocation[2] + a * rt->V[1]->GLocation[2];
+                                               tmat_apply_transform_44d(rv[1].FrameBufferCoord,vp,rv[1].GLocation);
+
+                                               BLI_remlink(&rb->AllRenderLines, (void *)rt->RL[0]); rt->RL[0]->Item.pNext = rt->RL[0]->Item.pPrev = 0;
+                                               BLI_remlink(&rb->AllRenderLines, (void *)rt->RL[1]); rt->RL[1]->Item.pNext = rt->RL[1]->Item.pPrev = 0;
+                                               BLI_remlink(&rb->AllRenderLines, (void *)rt->RL[2]); rt->RL[2]->Item.pNext = rt->RL[2]->Item.pPrev = 0;
+
+                                               rl = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLine));
+                                               rls = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+                                               BLI_addtail(&rl->Segments, rls);
+                                               BLI_addtail(&rb->AllRenderLines, rl);
+                                               rl->L = &rv[1];
+                                               rl->R = &rv[0];
+                                               rl->TL = rt1;
+                                               rt1->RL[1] = rl;
+
+                                               rl = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLine));
+                                               rls = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+                                               BLI_addtail(&rl->Segments, rls);
+                                               BLI_addtail(&rb->AllRenderLines, rl);
+                                               rl->L = &rv[1];
+                                               rl->R = rt->V[0];
+                                               rl->TL = rt->RL[0]->TL == rt ? rt1 : rt->RL[0]->TL;
+                                               rl->TR = rt->RL[0]->TR == rt ? rt1 : rt->RL[0]->TR;
+                                               rt1->RL[0] = rl;
+
+                                               rl = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLine));
+                                               rls = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+                                               BLI_addtail(&rl->Segments, rls);
+                                               BLI_addtail(&rb->AllRenderLines, rl);
+                                               rl->L = rt->V[0];
+                                               rl->R = &rv[0];
+                                               rl->TL = rt->RL[2]->TL == rt ? rt1 : rt->RL[2]->TL;
+                                               rl->TR = rt->RL[2]->TR == rt ? rt1 : rt->RL[2]->TR;
+                                               rt1->RL[2] = rl;
+
+                                               rt1->V[0] = rt->V[0];
+                                               rt1->V[1] = &rv[1];
+                                               rt1->V[2] = &rv[0];
+
+                                               lanpr_post_triangle(rt1, rt);
+
+                                               v_count += 2;
+                                               t_count += 1;
+                                               continue;
+                                       } elif(!In3) {
+                                               tMatVectorMinus3d(vv1,rt->V[2]->GLocation,cam_pos);
+                                               tMatVectorMinus3d(vv2,cam_pos,rt->V[0]->GLocation);
+                                               dot1 = tmat_dot_3d(vv1,view_dir,0);
+                                               dot2 = tmat_dot_3d(vv2,view_dir,0);
+                                               a = dot1/(dot1+dot2);
+                                               rv[0].GLocation[0] = (1-a) * rt->V[2]->GLocation[0] + a * rt->V[0]->GLocation[0];
+                                               rv[0].GLocation[1] = (1-a) * rt->V[2]->GLocation[1] + a * rt->V[0]->GLocation[1];
+                                               rv[0].GLocation[2] = (1-a) * rt->V[2]->GLocation[2] + a * rt->V[0]->GLocation[2];
+                                               tmat_apply_transform_44d(rv[0].FrameBufferCoord,vp,rv[0].GLocation);
+
+                                               tMatVectorMinus3d(vv1,rt->V[2]->GLocation,cam_pos);
+                                               tMatVectorMinus3d(vv2,cam_pos,rt->V[1]->GLocation);
+                                               dot1 = tmat_dot_3d(vv1,view_dir,0);
+                                               dot2 = tmat_dot_3d(vv2,view_dir,0);
+                                               a = dot1/(dot1+dot2);
+                                               rv[1].GLocation[0] = (1-a) * rt->V[2]->GLocation[0] + a * rt->V[1]->GLocation[0];
+                                               rv[1].GLocation[1] = (1-a) * rt->V[2]->GLocation[1] + a * rt->V[1]->GLocation[1];
+                                               rv[1].GLocation[2] = (1-a) * rt->V[2]->GLocation[2] + a * rt->V[1]->GLocation[2];
+                                               tmat_apply_transform_44d(rv[1].FrameBufferCoord,vp,rv[1].GLocation);
+
+                                               BLI_remlink(&rb->AllRenderLines, (void *)rt->RL[0]); rt->RL[0]->Item.pNext = rt->RL[0]->Item.pPrev = 0;
+                                               BLI_remlink(&rb->AllRenderLines, (void *)rt->RL[1]); rt->RL[1]->Item.pNext = rt->RL[1]->Item.pPrev = 0;
+                                               BLI_remlink(&rb->AllRenderLines, (void *)rt->RL[2]); rt->RL[2]->Item.pNext = rt->RL[2]->Item.pPrev = 0;
+
+                                               rl = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLine));
+                                               rls = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+                                               BLI_addtail(&rl->Segments, rls);
+                                               BLI_addtail(&rb->AllRenderLines, rl);
+                                               rl->L = &rv[0];
+                                               rl->R = &rv[1];
+                                               rl->TL = rt1;
+                                               rt1->RL[0] = rl;
+
+                                               rl = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLine));
+                                               rls = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+                                               BLI_addtail(&rl->Segments, rls);
+                                               BLI_addtail(&rb->AllRenderLines, rl);
+                                               rl->L = &rv[1];
+                                               rl->R = rt->V[2];
+                                               rl->TL = rt->RL[1]->TL == rt ? rt1 : rt->RL[1]->TL;
+                                               rl->TR = rt->RL[1]->TR == rt ? rt1 : rt->RL[1]->TR;
+                                               rt1->RL[1] = rl;
+
+                                               rl = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLine));
+                                               rls = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+                                               BLI_addtail(&rl->Segments, rls);
+                                               BLI_addtail(&rb->AllRenderLines, rl);
+                                               rl->L = rt->V[2];
+                                               rl->R = &rv[0];
+                                               rl->TL = rt->RL[2]->TL == rt ? rt1 : rt->RL[2]->TL;
+                                               rl->TR = rt->RL[2]->TR == rt ? rt1 : rt->RL[2]->TR;
+                                               rt1->RL[2] = rl;
+
+                                               rt1->V[0] = &rv[1];
+                                               rt1->V[1] = rt->V[2];
+                                               rt1->V[2] = &rv[0];
+
+                                               lanpr_post_triangle(rt1, rt);
+
+                                               v_count += 2;
+                                               t_count += 1;
+                                               continue;
+                                       } elif(!In2)
+                                       {
+                                               tMatVectorMinus3d(vv1,rt->V[1]->GLocation,cam_pos);
+                                               tMatVectorMinus3d(vv2,cam_pos,rt->V[2]->GLocation);
+                                               dot1 = tmat_dot_3d(vv1,view_dir,0);
+                                               dot2 = tmat_dot_3d(vv2,view_dir,0);
+                                               a = dot1/(dot1+dot2);
+                                               rv[0].GLocation[0] = (1-a) * rt->V[1]->GLocation[0] + a * rt->V[2]->GLocation[0];
+                                               rv[0].GLocation[1] = (1-a) * rt->V[1]->GLocation[1] + a * rt->V[2]->GLocation[1];
+                                               rv[0].GLocation[2] = (1-a) * rt->V[1]->GLocation[2] + a * rt->V[2]->GLocation[2];
+                                               tmat_apply_transform_44d(rv[0].FrameBufferCoord,vp,rv[0].GLocation);
+
+                                               tMatVectorMinus3d(vv1,rt->V[1]->GLocation,cam_pos);
+                                               tMatVectorMinus3d(vv2,cam_pos,rt->V[0]->GLocation);
+                                               dot1 = tmat_dot_3d(vv1,view_dir,0);
+                                               dot2 = tmat_dot_3d(vv2,view_dir,0);
+                                               a = dot1/(dot1+dot2);
+                                               rv[1].GLocation[0] = (1-a) * rt->V[1]->GLocation[0] + a * rt->V[0]->GLocation[0];
+                                               rv[1].GLocation[1] = (1-a) * rt->V[1]->GLocation[1] + a * rt->V[0]->GLocation[1];
+                                               rv[1].GLocation[2] = (1-a) * rt->V[1]->GLocation[2] + a * rt->V[0]->GLocation[2];
+                                               tmat_apply_transform_44d(rv[1].FrameBufferCoord,vp,rv[1].GLocation);
+
+                                               BLI_remlink(&rb->AllRenderLines, (void *)rt->RL[0]); rt->RL[0]->Item.pNext = rt->RL[0]->Item.pPrev = 0;
+                                               BLI_remlink(&rb->AllRenderLines, (void *)rt->RL[1]); rt->RL[1]->Item.pNext = rt->RL[1]->Item.pPrev = 0;
+                                               BLI_remlink(&rb->AllRenderLines, (void *)rt->RL[2]); rt->RL[2]->Item.pNext = rt->RL[2]->Item.pPrev = 0;
+
+                                               rl = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLine));
+                                               rls = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+                                               BLI_addtail(&rl->Segments, rls);
+                                               BLI_addtail(&rb->AllRenderLines, rl);
+                                               rl->L = &rv[1];
+                                               rl->R = &rv[0];
+                                               rl->TL = rt1;
+                                               rt1->RL[2] = rl;
+
+                                               rl = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLine));
+                                               rls = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+                                               BLI_addtail(&rl->Segments, rls);
+                                               BLI_addtail(&rb->AllRenderLines, rl);
+                                               rl->L = &rv[0];
+                                               rl->R = rt->V[1];
+                                               rl->TL = rt->RL[0]->TL == rt ? rt1 : rt->RL[0]->TL;
+                                               rl->TR = rt->RL[0]->TR == rt ? rt1 : rt->RL[0]->TR;
+                                               rt1->RL[0] = rl;
+
+                                               rl = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLine));
+                                               rls = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+                                               BLI_addtail(&rl->Segments, rls);
+                                               BLI_addtail(&rb->AllRenderLines, rl);
+                                               rl->L = rt->V[1];
+                                               rl->R = &rv[1];
+                                               rl->TL = rt->RL[1]->TL == rt ? rt1 : rt->RL[1]->TL;
+                                               rl->TR = rt->RL[1]->TR == rt ? rt1 : rt->RL[1]->TR;
+                                               rt1->RL[1] = rl;
+
+                                               rt1->V[0] = rt->V[1];
+                                               rt1->V[1] = &rv[1];
+                                               rt1->V[2] = &rv[0];
+
+                                               lanpr_post_triangle(rt1, rt);
+
+                                               v_count += 2;
+                                               t_count += 1;
+                                               continue;
+                                       }
+                                       break;
+                               case 1:
+                                       rt->CullStatus = TNS_CULL_USED;
+                                       if (In1) {
+                                               tMatVectorMinus3d(vv1,rt->V[0]->GLocation,cam_pos);
+                                               tMatVectorMinus3d(vv2,cam_pos,rt->V[2]->GLocation);
+                                               dot1 = tmat_dot_3d(vv1,view_dir,0);
+                                               dot2 = tmat_dot_3d(vv2,view_dir,0);
+                                               a = dot1/(dot1+dot2);
+                                               rv[0].GLocation[0] = (1-a) * rt->V[0]->GLocation[0] + a * rt->V[2]->GLocation[0];
+                                               rv[0].GLocation[1] = (1-a) * rt->V[0]->GLocation[1] + a * rt->V[2]->GLocation[1];
+                                               rv[0].GLocation[2] = (1-a) * rt->V[0]->GLocation[2] + a * rt->V[2]->GLocation[2];
+                                               tmat_apply_transform_44d(rv[0].FrameBufferCoord,vp,rv[0].GLocation);
+
+                                               tMatVectorMinus3d(vv1,rt->V[0]->GLocation,cam_pos);
+                                               tMatVectorMinus3d(vv2,cam_pos,rt->V[1]->GLocation);
+                                               dot1 = tmat_dot_3d(vv1,view_dir,0);
+                                               dot2 = tmat_dot_3d(vv2,view_dir,0);
+                                               a = dot1/(dot1+dot2);
+                                               rv[1].GLocation[0] = (1-a) * rt->V[0]->GLocation[0] + a * rt->V[1]->GLocation[0];
+                                               rv[1].GLocation[1] = (1-a) * rt->V[0]->GLocation[1] + a * rt->V[1]->GLocation[1];
+                                               rv[1].GLocation[2] = (1-a) * rt->V[0]->GLocation[2] + a * rt->V[1]->GLocation[2];
+                                               tmat_apply_transform_44d(rv[1].FrameBufferCoord,vp,rv[1].GLocation);
+
+                                               BLI_remlink(&rb->AllRenderLines, (void *)rt->RL[0]); rt->RL[0]->Item.pNext = rt->RL[0]->Item.pPrev = 0;
+                                               BLI_remlink(&rb->AllRenderLines, (void *)rt->RL[2]); rt->RL[2]->Item.pNext = rt->RL[2]->Item.pPrev = 0;
+
+                                               rl = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLine));
+                                               rls = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+                                               BLI_addtail(&rl->Segments, rls);
+                                               BLI_addtail(&rb->AllRenderLines, rl);
+                                               rl->L = &rv[1];
+                                               rl->R = &rv[0];
+                                               rl->TL = rt1;
+                                               rt1->RL[1] = rl;
+
+                                               rl = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLine));
+                                               rls = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+                                               BLI_addtail(&rl->Segments, rls);
+                                               BLI_addtail(&rb->AllRenderLines, rl);
+                                               rl->L = &rv[0];
+                                               rl->R = rt->V[1];
+                                               rl->TL = rt1;
+                                               rl->TR = rt2;
+                                               rt1->RL[2] = rl;
+                                               rt2->RL[0] = rl;
+
+                                               rl = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLine));
+                                               rls = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+                                               BLI_addtail(&rl->Segments, rls);
+                                               BLI_addtail(&rb->AllRenderLines, rl);
+                                               rl->L = rt->V[1];
+                                               rl->R = &rv[1];
+                                               rl->TL = rt->RL[0]->TL == rt ? rt1 : rt->RL[0]->TL;
+                                               rl->TR = rt->RL[0]->TR == rt ? rt1 : rt->RL[0]->TR;
+                                               rt1->RL[0] = rl;
+
+                                               rt1->V[0] = rt->V[1];
+                                               rt1->V[1] = &rv[1];
+                                               rt1->V[2] = &rv[0];
+
+                                               rl = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLine));
+                                               rls = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+                                               BLI_addtail(&rl->Segments, rls);
+                                               BLI_addtail(&rb->AllRenderLines, rl);
+                                               rl->L = rt->V[2];
+                                               rl->R = &rv[0];
+                                               rl->TL = rt->RL[2]->TL == rt ? rt1 : rt->RL[2]->TL;
+                                               rl->TR = rt->RL[2]->TR == rt ? rt1 : rt->RL[2]->TR;
+                                               rt2->RL[2] = rl;
+                                               rt2->RL[1] = rt->RL[1];
+
+                                               rt2->V[0] = &rv[0];
+                                               rt2->V[1] = rt->V[1];
+                                               rt2->V[2] = rt->V[2];
+
+                                               lanpr_post_triangle(rt1, rt);
+                                               lanpr_post_triangle(rt2, rt);
+
+                                               v_count += 2;
+                                               t_count += 2;
+                                               continue;
+                                       } elif(In2)     {
+
+                                               tMatVectorMinus3d(vv1,rt->V[1]->GLocation,cam_pos);
+                                               tMatVectorMinus3d(vv2,cam_pos,rt->V[2]->GLocation);
+                                               dot1 = tmat_dot_3d(vv1,view_dir,0);
+                                               dot2 = tmat_dot_3d(vv2,view_dir,0);
+                                               a = dot1/(dot1+dot2);
+                                               rv[0].GLocation[0] = (1-a) * rt->V[1]->GLocation[0] + a * rt->V[2]->GLocation[0];
+                                               rv[0].GLocation[1] = (1-a) * rt->V[1]->GLocation[1] + a * rt->V[2]->GLocation[1];
+                                               rv[0].GLocation[2] = (1-a) * rt->V[1]->GLocation[2] + a * rt->V[2]->GLocation[2];
+                                               tmat_apply_transform_44d(rv[0].FrameBufferCoord,vp,rv[0].GLocation);
+
+                                               tMatVectorMinus3d(vv1,rt->V[1]->GLocation,cam_pos);
+                                               tMatVectorMinus3d(vv2,cam_pos,rt->V[0]->GLocation);
+                                               dot1 = tmat_dot_3d(vv1,view_dir,0);
+                                               dot2 = tmat_dot_3d(vv2,view_dir,0);
+                                               a = dot1/(dot1+dot2);
+                                               rv[1].GLocation[0] = (1-a) * rt->V[1]->GLocation[0] + a * rt->V[0]->GLocation[0];
+                                               rv[1].GLocation[1] = (1-a) * rt->V[1]->GLocation[1] + a * rt->V[0]->GLocation[1];
+                                               rv[1].GLocation[2] = (1-a) * rt->V[1]->GLocation[2] + a * rt->V[0]->GLocation[2];
+                                               tmat_apply_transform_44d(rv[1].FrameBufferCoord,vp,rv[1].GLocation);
+
+                                               BLI_remlink(&rb->AllRenderLines, (void *)rt->RL[0]); rt->RL[0]->Item.pNext = rt->RL[0]->Item.pPrev = 0;
+                                               BLI_remlink(&rb->AllRenderLines, (void *)rt->RL[1]); rt->RL[1]->Item.pNext = rt->RL[1]->Item.pPrev = 0;
+
+                                               rl = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLine));
+                                               rls = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+                                               BLI_addtail(&rl->Segments, rls);
+                                               BLI_addtail(&rb->AllRenderLines, rl);
+                                               rl->L = &rv[1];
+                                               rl->R = &rv[0];
+                                               rl->TL = rt1;
+                                               rt1->RL[1] = rl;
+
+                                               rl = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLine));
+                                               rls = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+                                               BLI_addtail(&rl->Segments, rls);
+                                               BLI_addtail(&rb->AllRenderLines, rl);
+                                               rl->L = &rv[0];
+                                               rl->R = rt->V[2];
+                                               rl->TL = rt1;
+                                               rl->TR = rt2;
+                                               rt1->RL[2] = rl;
+                                               rt2->RL[0] = rl;
+
+                                               rl = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLine));
+                                               rls = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+                                               BLI_addtail(&rl->Segments, rls);
+                                               BLI_addtail(&rb->AllRenderLines, rl);
+                                               rl->L = rt->V[2];
+                                               rl->R = &rv[1];
+                                               rl->TL = rt->RL[1]->TL == rt ? rt1 : rt->RL[1]->TL;
+                                               rl->TR = rt->RL[1]->TR == rt ? rt1 : rt->RL[1]->TR;
+                                               rt1->RL[0] = rl;
+
+                                               rt1->V[0] = rt->V[2];
+                                               rt1->V[1] = &rv[1];
+                                               rt1->V[2] = &rv[0];
+
+                                               rl = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLine));
+                                               rls = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+                                               BLI_addtail(&rl->Segments, rls);
+                                               BLI_addtail(&rb->AllRenderLines, rl);
+                                               rl->L = rt->V[0];
+                                               rl->R = &rv[0];
+                                               rl->TL = rt->RL[0]->TL == rt ? rt1 : rt->RL[0]->TL;
+                                               rl->TR = rt->RL[0]->TR == rt ? rt1 : rt->RL[0]->TR;
+                                               rt2->RL[2] = rl;
+                                               rt2->RL[1] = rt->RL[2];
+
+                                               rt2->V[0] = &rv[0];
+                                               rt2->V[1] = rt->V[2];
+                                               rt2->V[2] = rt->V[0];
+
+                                               lanpr_post_triangle(rt1, rt);
+                                               lanpr_post_triangle(rt2, rt);
+
+                                               v_count += 2;
+                                               t_count += 2;
+                                               continue;
+                                       } elif(In3) {
+
+                                               tMatVectorMinus3d(vv1,rt->V[2]->GLocation,cam_pos);
+                                               tMatVectorMinus3d(vv2,cam_pos,rt->V[0]->GLocation);
+                                               dot1 = tmat_dot_3d(vv1,view_dir,0);
+                                               dot2 = tmat_dot_3d(vv2,view_dir,0);
+                                               a = dot1/(dot1+dot2);
+                                               rv[0].GLocation[0] = (1-a) * rt->V[2]->GLocation[0] + a * rt->V[0]->GLocation[0];
+                                               rv[0].GLocation[1] = (1-a) * rt->V[2]->GLocation[1] + a * rt->V[0]->GLocation[1];
+                                               rv[0].GLocation[2] = (1-a) * rt->V[2]->GLocation[2] + a * rt->V[0]->GLocation[2];
+                                               tmat_apply_transform_44d(rv[0].FrameBufferCoord,vp,rv[0].GLocation);
+
+                                               tMatVectorMinus3d(vv1,rt->V[2]->GLocation,cam_pos);
+                                               tMatVectorMinus3d(vv2,cam_pos,rt->V[1]->GLocation);
+                                               dot1 = tmat_dot_3d(vv1,view_dir,0);
+                                               dot2 = tmat_dot_3d(vv2,view_dir,0);
+                                               a = dot1/(dot1+dot2);
+                                               rv[1].GLocation[0] = (1-a) * rt->V[2]->GLocation[0] + a * rt->V[1]->GLocation[0];
+                                               rv[1].GLocation[1] = (1-a) * rt->V[2]->GLocation[1] + a * rt->V[1]->GLocation[1];
+                                               rv[1].GLocation[2] = (1-a) * rt->V[2]->GLocation[2] + a * rt->V[1]->GLocation[2];
+                                               tmat_apply_transform_44d(rv[1].FrameBufferCoord,vp,rv[1].GLocation);
+
+                                               BLI_remlink(&rb->AllRenderLines, (void *)rt->RL[1]); rt->RL[1]->Item.pNext = rt->RL[1]->Item.pPrev = 0;
+                                               BLI_remlink(&rb->AllRenderLines, (void *)rt->RL[2]); rt->RL[2]->Item.pNext = rt->RL[2]->Item.pPrev = 0;
+
+                                               rl = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLine));
+                                               rls = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+                                               BLI_addtail(&rl->Segments, rls);
+                                               BLI_addtail(&rb->AllRenderLines, rl);
+                                               rl->L = &rv[1];
+                                               rl->R = &rv[0];
+                                               rl->TL = rt1;
+                                               rt1->RL[1] = rl;
+
+                                               rl = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLine));
+                                               rls = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+                                               BLI_addtail(&rl->Segments, rls);
+                                               BLI_addtail(&rb->AllRenderLines, rl);
+                                               rl->L = &rv[0];
+                                               rl->R = rt->V[0];
+                                               rl->TL = rt1;
+                                               rl->TR = rt2;
+                                               rt1->RL[2] = rl;
+                                               rt2->RL[0] = rl;
+
+                                               rl = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLine));
+                                               rls = mem_static_aquire(&rb->RenderDataPool, sizeof(LANPR_RenderLineSegment));
+                                               BLI_addtail(&rl->Segments, rls);
+                                               BLI_addtail(&rb->AllRenderLines, rl);
+                                               rl->L = rt->V[0];
+                                               rl->R = &rv[1];
+                                               rl->TL = rt->RL[0]->TL == rt ? rt1 : rt->RL[0]->TL;
+                                               rl->TR = rt->RL[0]->TR == rt ? rt1 : rt->RL[0]->TR;
+                                               rt1->RL[0] = rl;
+
+                                               rt1->V[0] = rt->V[0];
+                                               rt1->V[1] = &rv[1];
+                                               rt1->V[2] = &rv[0];
+
+