Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2016-02-18 03:35:52 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2016-02-18 22:05:57 +0300
commit01360463352736eebb5f42ad7ae7d61530615b84 (patch)
treeae26b36d001fbe1a2a615b3b035c2d5c8b228466 /source
parent1a676d4e0e57647a36c5e98aae56e588da101a2c (diff)
Fix T45343: incorrect Cycles baking of bump maps from selected to active.
The differentials were incorrect, now they are properly transferred from the low to the high poly mesh.
Diffstat (limited to 'source')
-rw-r--r--source/blender/render/intern/include/shading.h4
-rw-r--r--source/blender/render/intern/source/bake_api.c96
-rw-r--r--source/blender/render/intern/source/shadeinput.c57
3 files changed, 93 insertions, 64 deletions
diff --git a/source/blender/render/intern/include/shading.h b/source/blender/render/intern/include/shading.h
index 11dcc9d9e80..27867eadbb4 100644
--- a/source/blender/render/intern/include/shading.h
+++ b/source/blender/render/intern/include/shading.h
@@ -82,6 +82,10 @@ void vlr_set_uv_indices(struct VlakRen *vlr, int *i1, int *i2, int *i3);
void calc_R_ref(struct ShadeInput *shi);
+void barycentric_differentials_from_position(
+ const float co[3], const float v1[3], const float v2[3], const float v3[3],
+ const float dxco[3], const float dyco[3], const float facenor[3], const bool differentials,
+ float *u, float *v, float *dx_u, float *dx_v, float *dy_u, float *dy_v);
/* shadeoutput. */
void shade_lamp_loop(struct ShadeInput *shi, struct ShadeResult *shr);
diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c
index 21460c701e6..63aa0d59bfa 100644
--- a/source/blender/render/intern/source/bake_api.c
+++ b/source/blender/render/intern/source/bake_api.c
@@ -84,6 +84,7 @@
/* local include */
#include "render_types.h"
+#include "shading.h"
#include "zbuf.h"
/* Remove when Cycles moves from MFace to MLoopTri */
@@ -263,31 +264,14 @@ static void calc_point_from_barycentric_extrusion(
}
/**
- * This function returns the barycentric u,v of a face for a coordinate. The face is defined by its index.
- */
-static void calc_barycentric_from_point(
- TriTessFace *triangles, const int index, const float co[3],
- int *r_primitive_id, float r_uv[2])
-{
- TriTessFace *triangle = &triangles[index];
- resolve_tri_uv_v3(r_uv, co,
- triangle->mverts[0]->co,
- triangle->mverts[1]->co,
- triangle->mverts[2]->co);
- *r_primitive_id = index;
-}
-
-/**
* This function populates pixel_array and returns TRUE if things are correct
*/
static bool cast_ray_highpoly(
- BVHTreeFromMesh *treeData, TriTessFace *triangles[], BakePixel *pixel_array, BakeHighPolyData *highpoly,
- const float co[3], const float dir[3], const int pixel_id, const int tot_highpoly,
- const float du_dx, const float du_dy, const float dv_dx, const float dv_dy)
+ BVHTreeFromMesh *treeData, TriTessFace *triangle_low, TriTessFace *triangles[],
+ BakePixel *pixel_array_low, BakePixel *pixel_array, float mat_low[4][4], BakeHighPolyData *highpoly,
+ const float co[3], const float dir[3], const int pixel_id, const int tot_highpoly)
{
int i;
- int primitive_id = -1;
- float uv[2];
int hit_mesh = -1;
float hit_distance = FLT_MAX;
@@ -333,17 +317,47 @@ static bool cast_ray_highpoly(
}
if (hit_mesh != -1) {
- calc_barycentric_from_point(triangles[hit_mesh], hits[hit_mesh].index, hits[hit_mesh].co, &primitive_id, uv);
- pixel_array[pixel_id].primitive_id = primitive_id;
+ int primitive_id_high = hits[hit_mesh].index;
+ TriTessFace *triangle_high = &triangles[hit_mesh][primitive_id_high];
+
+ pixel_array[pixel_id].primitive_id = primitive_id_high;
pixel_array[pixel_id].object_id = hit_mesh;
- copy_v2_v2(pixel_array[pixel_id].uv, uv);
- /* the differentials are relative to the UV/image space, so the highpoly differentials
- * are the same as the low poly differentials */
- pixel_array[pixel_id].du_dx = du_dx;
- pixel_array[pixel_id].du_dy = du_dy;
- pixel_array[pixel_id].dv_dx = dv_dx;
- pixel_array[pixel_id].dv_dy = dv_dy;
+ /* ray direction in high poly object space */
+ float dir_high[3];
+ mul_v3_mat3_m4v3(dir_high, highpoly[hit_mesh].imat, dir);
+ normalize_v3(dir_high);
+
+ /* compute position differentials on low poly object */
+ float duco_low[3], dvco_low[3], dxco[3], dyco[3];
+ sub_v3_v3v3(duco_low, triangle_low->mverts[0]->co, triangle_low->mverts[2]->co);
+ sub_v3_v3v3(dvco_low, triangle_low->mverts[1]->co, triangle_low->mverts[2]->co);
+
+ mul_v3_v3fl(dxco, duco_low, pixel_array_low[pixel_id].du_dx);
+ madd_v3_v3fl(dxco, dvco_low, pixel_array_low[pixel_id].dv_dx);
+ mul_v3_v3fl(dyco, duco_low, pixel_array_low[pixel_id].du_dy);
+ madd_v3_v3fl(dyco, dvco_low, pixel_array_low[pixel_id].dv_dy);
+
+ /* transform from low poly to to high poly object space */
+ mul_mat3_m4_v3(mat_low, dxco);
+ mul_mat3_m4_v3(mat_low, dyco);
+ mul_mat3_m4_v3(highpoly[hit_mesh].imat, dxco);
+ mul_mat3_m4_v3(highpoly[hit_mesh].imat, dyco);
+
+ /* transfer position differentials */
+ float tmp[3];
+ mul_v3_v3fl(tmp, dir_high, 1.0f/dot_v3v3(dir_high, triangle_high->normal));
+ madd_v3_v3fl(dxco, tmp, -dot_v3v3(dxco, triangle_high->normal));
+ madd_v3_v3fl(dyco, tmp, -dot_v3v3(dyco, triangle_high->normal));
+
+ /* compute barycentric differentials from position differentials */
+ barycentric_differentials_from_position(
+ hits[hit_mesh].co, triangle_high->mverts[0]->co,
+ triangle_high->mverts[1]->co, triangle_high->mverts[2]->co,
+ dxco, dyco, triangle_high->normal, true,
+ &pixel_array[pixel_id].uv[0], &pixel_array[pixel_id].uv[1],
+ &pixel_array[pixel_id].du_dx, &pixel_array[pixel_id].dv_dx,
+ &pixel_array[pixel_id].du_dy, &pixel_array[pixel_id].dv_dy);
}
else {
pixel_array[pixel_id].primitive_id = -1;
@@ -441,17 +455,17 @@ static TriTessFace *mesh_calc_tri_tessface(
triangles[i].tspace[0] = &tspace[lt->tri[0]];
triangles[i].tspace[1] = &tspace[lt->tri[1]];
triangles[i].tspace[2] = &tspace[lt->tri[2]];
+ }
- if (calculate_normal) {
- if (lt->poly != mpoly_prev) {
- BKE_mesh_calc_poly_normal(mp, &me->mloop[mp->loopstart], me->mvert, no);
- mpoly_prev = lt->poly;
- }
- copy_v3_v3(triangles[i].normal, no);
- }
- else {
- copy_v3_v3(triangles[i].normal, &precomputed_normals[lt->poly]);
+ if (calculate_normal) {
+ if (lt->poly != mpoly_prev) {
+ BKE_mesh_calc_poly_normal(mp, &me->mloop[mp->loopstart], me->mvert, no);
+ mpoly_prev = lt->poly;
}
+ copy_v3_v3(triangles[i].normal, no);
+ }
+ else {
+ copy_v3_v3(triangles[i].normal, &precomputed_normals[lt->poly]);
}
}
@@ -546,9 +560,9 @@ bool RE_bake_pixels_populate_from_objects(
}
/* cast ray */
- if (!cast_ray_highpoly(treeData, tris_high, pixel_array_to, highpoly, co, dir, i, tot_highpoly,
- pixel_array_from[i].du_dx, pixel_array_from[i].du_dy,
- pixel_array_from[i].dv_dx, pixel_array_from[i].dv_dy)) {
+ if (!cast_ray_highpoly(treeData, &tris_low[primitive_id], tris_high,
+ pixel_array_from, pixel_array_to, mat_low,
+ highpoly, co, dir, i, tot_highpoly)) {
/* if it fails mask out the original pixel array */
pixel_array_from[i].primitive_id = -1;
}
diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c
index 05097bb8004..e60a5a70a7f 100644
--- a/source/blender/render/intern/source/shadeinput.c
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -705,6 +705,35 @@ void shade_input_set_viewco(ShadeInput *shi, float x, float y, float xs, float y
shade_input_calc_viewco(shi, xs, ys, z, shi->view, dxyview, shi->co, dxco, dyco);
}
+void barycentric_differentials_from_position(
+ const float co[3], const float v1[3], const float v2[3], const float v3[3],
+ const float dxco[3], const float dyco[3], const float facenor[3], const bool differentials,
+ float *u, float *v, float *dx_u, float *dx_v, float *dy_u, float *dy_v)
+{
+ /* find most stable axis to project */
+ int axis1, axis2;
+ axis_dominant_v3(&axis1, &axis2, facenor);
+
+ /* compute u,v and derivatives */
+ float t00 = v3[axis1] - v1[axis1];
+ float t01 = v3[axis2] - v1[axis2];
+ float t10 = v3[axis1] - v2[axis1];
+ float t11 = v3[axis2] - v2[axis2];
+
+ float detsh = (t00 * t11 - t10 * t01);
+ detsh = (detsh != 0.0f) ? 1.0f / detsh : 0.0f;
+ t00 *= detsh; t01 *= detsh;
+ t10 *= detsh; t11 *= detsh;
+
+ *u = (v3[axis1] - co[axis1]) * t11 - (v3[axis2] - co[axis2]) * t10;
+ *v = (v3[axis2] - co[axis2]) * t00 - (v3[axis1] - co[axis1]) * t01;
+ if (differentials) {
+ *dx_u = dxco[axis1] * t11 - dxco[axis2] * t10;
+ *dx_v = dxco[axis2] * t00 - dxco[axis1] * t01;
+ *dy_u = dyco[axis1] * t11 - dyco[axis2] * t10;
+ *dy_v = dyco[axis2] * t00 - dyco[axis1] * t01;
+ }
+}
/* calculate U and V, for scanline (silly render face u and v are in range -1 to 0) */
void shade_input_set_uv(ShadeInput *shi)
{
@@ -746,30 +775,12 @@ void shade_input_set_uv(ShadeInput *shi)
}
}
else {
- /* most of this could become re-used for faces */
- float detsh, t00, t10, t01, t11;
- int axis1, axis2;
-
- /* find most stable axis to project */
- axis_dominant_v3(&axis1, &axis2, shi->facenor);
+ barycentric_differentials_from_position(
+ shi->co, v1, v2, v3, shi->dxco, shi->dyco, shi->facenor, shi->osatex,
+ &shi->u, &shi->v, &shi->dx_u, &shi->dx_v, &shi->dy_u, &shi->dy_v);
- /* compute u,v and derivatives */
- t00 = v3[axis1] - v1[axis1]; t01 = v3[axis2] - v1[axis2];
- t10 = v3[axis1] - v2[axis1]; t11 = v3[axis2] - v2[axis2];
-
- detsh = (t00 * t11 - t10 * t01);
- detsh = (detsh != 0.0f) ? 1.0f / detsh : 0.0f;
- t00 *= detsh; t01 *= detsh;
- t10 *= detsh; t11 *= detsh;
-
- shi->u = (shi->co[axis1] - v3[axis1]) * t11 - (shi->co[axis2] - v3[axis2]) * t10;
- shi->v = (shi->co[axis2] - v3[axis2]) * t00 - (shi->co[axis1] - v3[axis1]) * t01;
- if (shi->osatex) {
- shi->dx_u = shi->dxco[axis1] * t11 - shi->dxco[axis2] * t10;
- shi->dx_v = shi->dxco[axis2] * t00 - shi->dxco[axis1] * t01;
- shi->dy_u = shi->dyco[axis1] * t11 - shi->dyco[axis2] * t10;
- shi->dy_v = shi->dyco[axis2] * t00 - shi->dyco[axis1] * t01;
- }
+ shi->u = -shi->u;
+ shi->v = -shi->v;
/* u and v are in range -1 to 0, we allow a little bit extra but not too much, screws up speedvectors */
CLAMP(shi->u, -2.0f, 1.0f);