Cycles: Fix triangle ribbons hair in viewport and ortho camera
authorSergey Sharybin <sergey.vfx@gmail.com>
Fri, 29 Aug 2014 10:44:16 +0000 (16:44 +0600)
committerSergey Sharybin <sergey.vfx@gmail.com>
Fri, 29 Aug 2014 10:44:16 +0000 (16:44 +0600)
There were several issues involved into triangle ribbons hair:

- Even for the viewport rendering the blender scene camera was
  used for orientation. This made hair triangles oriented to
  the scene camera, not to the viewport camera.

- Triangle orientation was actually supposing the camera is
  perspective. Triangles weren't oriented properly for the
  orthographic camera resulting in different hair width across
  it's length.

This issues are solved now, but there are some related TODOs:

- Rotating viewport doesn't re-orient the triangles, so after
  viewport navigation hair might not look correct. However,
  with this fix toggling viewport render (to force hair sync)
  makes viewport render correct.

  This isn't so much trivial fix, would require making BVH
  aware of the dynamic triangle orientation, so they get
  properly oriented without full hair re-sync.

- Panorama camera behavior didn't change but looks like it
  should, however not really sure atm what's the right thing
  to do here.

intern/cycles/blender/blender_curves.cpp
intern/cycles/blender/blender_session.cpp

index 7b1a8ec0b1598551f7e0e6e5a86297e95380796c..8cfaea59a06b9fc52344f9b364f5cfd331367844 100644 (file)
  */
 
 #include "attribute.h"
+#include "camera.h"
+#include "curves.h"
 #include "mesh.h"
 #include "object.h"
 #include "scene.h"
-#include "curves.h"
 
 #include "blender_sync.h"
 #include "blender_util.h"
@@ -39,7 +40,8 @@ bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Parti
 bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background, int vcol_num);
 bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background);
 void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData);
-void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, float3 RotCam);
+void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData,
+                               float3 RotCam, bool is_ortho);
 void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int resolution);
 void ExportCurveTriangleUV(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, float3 *uvdata);
 void ExportCurveTriangleVcol(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, uchar4 *cdata);
@@ -328,7 +330,8 @@ static void set_resolution(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, BL::S
        }
 }
 
-void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, float3 RotCam)
+void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData,
+                               float3 RotCam, bool is_ortho)
 {
        int vertexno = mesh->verts.size();
        int vertexindex = vertexno;
@@ -362,7 +365,10 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, float3 RotC
                        float3 ickey_loc = CData->curvekey_co[CData->curve_firstkey[curve]];
                        float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.0f);
                        v1 = CData->curvekey_co[CData->curve_firstkey[curve] + 1] - CData->curvekey_co[CData->curve_firstkey[curve]];
-                       xbasis = normalize(cross(RotCam - ickey_loc,v1));
+                       if(is_ortho)
+                               xbasis = normalize(cross(RotCam, v1));
+                       else
+                               xbasis = normalize(cross(RotCam - ickey_loc, v1));
                        float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
                        float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
                        mesh->verts.push_back(ickey_loc_shfl);
@@ -386,7 +392,10 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, float3 RotC
                                if(CData->psys_closetip[sys] && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
                                        radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
 
-                               xbasis = normalize(cross(RotCam - ickey_loc,v1));
+                               if(is_ortho)
+                                       xbasis = normalize(cross(RotCam, v1));
+                               else
+                                       xbasis = normalize(cross(RotCam - ickey_loc, v1));
                                float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
                                float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
                                mesh->verts.push_back(ickey_loc_shfl);
@@ -858,20 +867,26 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool
 
        ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, !preview);
 
-       /* obtain camera parameters */
-       BL::Object b_CamOb = b_scene.camera();
-       float3 RotCam = make_float3(0.0f, 0.0f, 0.0f);
-       if(b_CamOb) {
-               Transform ctfm = get_transform(b_CamOb.matrix_world());
-               Transform tfm = get_transform(b_ob.matrix_world());
-               Transform itfm = transform_quick_inverse(tfm);
-               RotCam = transform_point(&itfm, make_float3(ctfm.x.w, ctfm.y.w, ctfm.z.w));
-       }
-
        /* add hair geometry to mesh */
        if(primitive == CURVE_TRIANGLES) {
-               if(triangle_method == CURVE_CAMERA_TRIANGLES)
-                       ExportCurveTrianglePlanes(mesh, &CData, RotCam);
+               if(triangle_method == CURVE_CAMERA_TRIANGLES) {
+                       /* obtain camera parameters */
+                       float3 RotCam;
+                       Camera *camera = scene->camera;
+                       Transform &ctfm = camera->matrix;
+                       if(camera->type == CAMERA_ORTHOGRAPHIC) {
+                               RotCam = -make_float3(ctfm.x.z, ctfm.y.z, ctfm.z.z);
+                       }
+                       else {
+                               Transform tfm = get_transform(b_ob.matrix_world());
+                               Transform itfm = transform_quick_inverse(tfm);
+                               RotCam = transform_point(&itfm, make_float3(ctfm.x.w,
+                                                                           ctfm.y.w,
+                                                                           ctfm.z.w));
+                       }
+                       bool is_ortho = camera->type == CAMERA_ORTHOGRAPHIC;
+                       ExportCurveTrianglePlanes(mesh, &CData, RotCam, is_ortho);
+               }
                else {
                        ExportCurveTriangleGeometry(mesh, &CData, resolution);
                        used_res = resolution;
index 3e84110c335dad0ee67678a37b0e882535bba4ee..4ff3d89f9f1b9492c1967617c888636f2860c431 100644 (file)
@@ -116,8 +116,8 @@ void BlenderSession::create_session()
        if(b_v3d) {
                if(session_pause == false) {
                        /* full data sync */
-                       sync->sync_data(b_v3d, b_engine.camera_override(), &python_thread_state);
                        sync->sync_view(b_v3d, b_rv3d, width, height);
+                       sync->sync_data(b_v3d, b_engine.camera_override(), &python_thread_state);
                }
        }
        else {