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
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/render/intern/source/bake_api.c')
-rw-r--r--source/blender/render/intern/source/bake_api.c268
1 files changed, 169 insertions, 99 deletions
diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c
index dee75d43f36..eff021c9b14 100644
--- a/source/blender/render/intern/source/bake_api.c
+++ b/source/blender/render/intern/source/bake_api.c
@@ -84,8 +84,11 @@
/* local include */
#include "render_types.h"
+#include "shading.h"
#include "zbuf.h"
+/* Remove when Cycles moves from MFace to MLoopTri */
+#define USE_MFACE_WORKAROUND
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
@@ -261,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;
@@ -297,7 +283,7 @@ static bool cast_ray_highpoly(
hits[i].index = -1;
/* TODO: we should use FLT_MAX here, but sweepsphere code isn't prepared for that */
- hits[i].dist = 10000.0f;
+ hits[i].dist = BVH_RAYCAST_DIST_MAX;
/* transform the ray from the world space to the highpoly space */
mul_v3_m4v3(co_high, highpoly[i].imat, co);
@@ -331,17 +317,54 @@ 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;
- 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;
+ int primitive_id_high = hits[hit_mesh].index;
+ TriTessFace *triangle_high = &triangles[hit_mesh][primitive_id_high];
+ BakePixel *pixel_low = &pixel_array_low[pixel_id];
+ BakePixel *pixel_high = &pixel_array[pixel_id];
+
+ pixel_high->primitive_id = primitive_id_high;
+ pixel_high->object_id = hit_mesh;
+
+ /* 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_low->du_dx);
+ madd_v3_v3fl(dxco, dvco_low, pixel_low->dv_dx);
+ mul_v3_v3fl(dyco, duco_low, pixel_low->du_dy);
+ madd_v3_v3fl(dyco, dvco_low, pixel_low->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_high->uv[0], &pixel_high->uv[1],
+ &pixel_high->du_dx, &pixel_high->dv_dx,
+ &pixel_high->du_dy, &pixel_high->dv_dy);
+
+ /* verify we have valid uvs */
+ BLI_assert(pixel_high->uv[0] >= -1e-3f &&
+ pixel_high->uv[1] >= -1e-3f &&
+ pixel_high->uv[0] + pixel_high->uv[1] <= 1.0f + 1e-3f);
}
else {
pixel_array[pixel_id].primitive_id = -1;
@@ -352,34 +375,58 @@ static bool cast_ray_highpoly(
return hit_mesh != -1;
}
+#ifdef USE_MFACE_WORKAROUND
+/**
+ * Until cycles moves to #MLoopTri, we need to keep face-rotation in sync with #test_index_face
+ *
+ * We only need to consider quads since #BKE_mesh_recalc_tessellation doesn't execute this on triangles.
+ */
+static void test_index_face_looptri(const MPoly *mp, MLoop *mloop, MLoopTri *lt)
+{
+ if (mp->totloop == 4) {
+ if (UNLIKELY((mloop[mp->loopstart + 2].v == 0) ||
+ (mloop[mp->loopstart + 3].v == 0)))
+ {
+ /* remap: (2, 3, 0, 1) */
+ unsigned int l = mp->loopstart;
+ ARRAY_SET_ITEMS(lt[0].tri, l + 2, l + 3, l + 0);
+ ARRAY_SET_ITEMS(lt[1].tri, l + 2, l + 0, l + 1);
+ }
+ }
+}
+#endif
+
/**
* This function populates an array of verts for the triangles of a mesh
* Tangent and Normals are also stored
*/
-static void mesh_calc_tri_tessface(
- TriTessFace *triangles, Mesh *me, bool tangent, DerivedMesh *dm)
+static TriTessFace *mesh_calc_tri_tessface(
+ Mesh *me, bool tangent, DerivedMesh *dm)
{
int i;
MVert *mvert;
TSpace *tspace;
- float *precomputed_normals = NULL;
- bool calculate_normal;
+
const int tottri = poly_to_tri_count(me->totpoly, me->totloop);
MLoopTri *looptri;
+ TriTessFace *triangles;
+
/* calculate normal for each polygon only once */
unsigned int mpoly_prev = UINT_MAX;
float no[3];
+#ifdef USE_MFACE_WORKAROUND
+ unsigned int mpoly_prev_testindex = UINT_MAX;
+#endif
+
mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__);
+ triangles = MEM_mallocN(sizeof(TriTessFace) * tottri, __func__);
if (tangent) {
DM_ensure_normals(dm);
DM_calc_loop_tangents(dm);
- precomputed_normals = dm->getPolyDataArray(dm, CD_NORMAL);
- calculate_normal = precomputed_normals ? false : true;
-
tspace = dm->getLoopDataArray(dm, CD_TANGENT);
BLI_assert(tspace);
}
@@ -390,9 +437,20 @@ static void mesh_calc_tri_tessface(
me->totloop, me->totpoly,
looptri);
+
+ const float *precomputed_normals = dm ? dm->getPolyDataArray(dm, CD_NORMAL) : NULL;
+ const bool calculate_normal = precomputed_normals ? false : true;
+
for (i = 0; i < tottri; i++) {
- MLoopTri *lt = &looptri[i];
- MPoly *mp = &me->mpoly[lt->poly];
+ const MLoopTri *lt = &looptri[i];
+ const MPoly *mp = &me->mpoly[lt->poly];
+
+#ifdef USE_MFACE_WORKAROUND
+ if (lt->poly != mpoly_prev_testindex) {
+ test_index_face_looptri(mp, me->mloop, &looptri[i]);
+ mpoly_prev_testindex = lt->poly;
+ }
+#endif
triangles[i].mverts[0] = &mvert[me->mloop[lt->tri[0]].v];
triangles[i].mverts[1] = &mvert[me->mloop[lt->tri[1]].v];
@@ -403,22 +461,23 @@ static void 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) {
- const MPoly *mp = &me->mpoly[lt->poly];
- 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]);
}
}
MEM_freeN(looptri);
+
+ return triangles;
}
bool RE_bake_pixels_populate_from_objects(
@@ -451,26 +510,20 @@ bool RE_bake_pixels_populate_from_objects(
if (!is_cage) {
dm_low = CDDM_from_mesh(me_low);
- tris_low = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Lowpoly Mesh");
- mesh_calc_tri_tessface(tris_low, me_low, true, dm_low);
+ tris_low = mesh_calc_tri_tessface(me_low, true, dm_low);
}
else if (is_custom_cage) {
- tris_low = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Lowpoly Mesh");
- mesh_calc_tri_tessface(tris_low, me_low, false, NULL);
-
- tris_cage = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Cage Mesh");
- mesh_calc_tri_tessface(tris_cage, me_cage, false, NULL);
+ tris_low = mesh_calc_tri_tessface(me_low, false, NULL);
+ tris_cage = mesh_calc_tri_tessface(me_cage, false, NULL);
}
else {
- tris_cage = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Cage Mesh");
- mesh_calc_tri_tessface(tris_cage, me_cage, false, NULL);
+ tris_cage = mesh_calc_tri_tessface(me_cage, false, NULL);
}
invert_m4_m4(imat_low, mat_low);
for (i = 0; i < tot_highpoly; i++) {
- tris_high[i] = MEM_mallocN(sizeof(TriTessFace) * highpoly[i].me->totface, "MVerts Highpoly Mesh");
- mesh_calc_tri_tessface(tris_high[i], highpoly[i].me, false, NULL);
+ tris_high[i] = mesh_calc_tri_tessface(highpoly[i].me, false, NULL);
dm_highpoly[i] = CDDM_from_mesh(highpoly[i].me);
DM_ensure_tessface(dm_highpoly[i]);
@@ -490,6 +543,7 @@ bool RE_bake_pixels_populate_from_objects(
for (i = 0; i < num_pixels; i++) {
float co[3];
float dir[3];
+ TriTessFace *tri_low;
primitive_id = pixel_array_from[i].primitive_id;
@@ -504,18 +558,21 @@ bool RE_bake_pixels_populate_from_objects(
/* calculate from low poly mesh cage */
if (is_custom_cage) {
calc_point_from_barycentric_cage(tris_low, tris_cage, mat_low, mat_cage, primitive_id, u, v, co, dir);
+ tri_low = &tris_cage[primitive_id];
}
else if (is_cage) {
calc_point_from_barycentric_extrusion(tris_cage, mat_low, imat_low, primitive_id, u, v, cage_extrusion, co, dir, true);
+ tri_low = &tris_cage[primitive_id];
}
else {
calc_point_from_barycentric_extrusion(tris_low, mat_low, imat_low, primitive_id, u, v, cage_extrusion, co, dir, false);
+ tri_low = &tris_low[primitive_id];
}
/* 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, tri_low, 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;
}
@@ -583,73 +640,84 @@ void RE_bake_pixels_populate(
size_t i;
int a, p_id;
- MTFace *mtface;
- MFace *mface;
+ const MLoopUV *mloopuv;
+ const int tottri = poly_to_tri_count(me->totpoly, me->totloop);
+ MLoopTri *looptri;
+#ifdef USE_MFACE_WORKAROUND
+ unsigned int mpoly_prev_testindex = UINT_MAX;
+#endif
- /* we can't bake in edit mode */
- if (me->edit_btmesh)
+ if ((uv_layer == NULL) || (uv_layer[0] == '\0')) {
+ mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
+ }
+ else {
+ int uv_id = CustomData_get_named_layer(&me->ldata, CD_MLOOPUV, uv_layer);
+ mloopuv = CustomData_get_layer_n(&me->ldata, CD_MTFACE, uv_id);
+ }
+
+ if (mloopuv == NULL)
return;
+
bd.pixel_array = pixel_array;
bd.zspan = MEM_callocN(sizeof(ZSpan) * bake_images->size, "bake zspan");
/* initialize all pixel arrays so we know which ones are 'blank' */
for (i = 0; i < num_pixels; i++) {
pixel_array[i].primitive_id = -1;
+ pixel_array[i].object_id = 0;
}
for (i = 0; i < bake_images->size; i++) {
zbuf_alloc_span(&bd.zspan[i], bake_images->data[i].width, bake_images->data[i].height, R.clipcrop);
}
- if ((uv_layer == NULL) || (uv_layer[0] == '\0')) {
- mtface = CustomData_get_layer(&me->fdata, CD_MTFACE);
- }
- else {
- int uv_id = CustomData_get_named_layer(&me->fdata, CD_MTFACE, uv_layer);
- mtface = CustomData_get_layer_n(&me->fdata, CD_MTFACE, uv_id);
- }
-
- mface = CustomData_get_layer(&me->fdata, CD_MFACE);
+ looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__);
- if (mtface == NULL)
- return;
+ BKE_mesh_recalc_looptri(
+ me->mloop, me->mpoly,
+ me->mvert,
+ me->totloop, me->totpoly,
+ looptri);
p_id = -1;
- for (i = 0; i < me->totface; i++) {
- float vec[4][2];
- MTFace *mtf = &mtface[i];
- MFace *mf = &mface[i];
- int mat_nr = mf->mat_nr;
+ for (i = 0; i < tottri; i++) {
+ const MLoopTri *lt = &looptri[i];
+ const MPoly *mp = &me->mpoly[lt->poly];
+ float vec[3][2];
+ int mat_nr = mp->mat_nr;
int image_id = bake_images->lookup[mat_nr];
bd.bk_image = &bake_images->data[image_id];
bd.primitive_id = ++p_id;
- for (a = 0; a < 4; a++) {
+#ifdef USE_MFACE_WORKAROUND
+ if (lt->poly != mpoly_prev_testindex) {
+ test_index_face_looptri(mp, me->mloop, &looptri[i]);
+ mpoly_prev_testindex = lt->poly;
+ }
+#endif
+
+ for (a = 0; a < 3; a++) {
+ const float *uv = mloopuv[lt->tri[a]].uv;
+
/* Note, workaround for pixel aligned UVs which are common and can screw up our intersection tests
* where a pixel gets in between 2 faces or the middle of a quad,
* camera aligned quads also have this problem but they are less common.
* Add a small offset to the UVs, fixes bug #18685 - Campbell */
- vec[a][0] = mtf->uv[a][0] * (float)bd.bk_image->width - (0.5f + 0.001f);
- vec[a][1] = mtf->uv[a][1] * (float)bd.bk_image->height - (0.5f + 0.002f);
+ vec[a][0] = uv[0] * (float)bd.bk_image->width - (0.5f + 0.001f);
+ vec[a][1] = uv[1] * (float)bd.bk_image->height - (0.5f + 0.002f);
}
bake_differentials(&bd, vec[0], vec[1], vec[2]);
zspan_scanconvert(&bd.zspan[image_id], (void *)&bd, vec[0], vec[1], vec[2], store_bake_pixel);
-
- /* 4 vertices in the face */
- if (mf->v4 != 0) {
- bd.primitive_id = ++p_id;
-
- bake_differentials(&bd, vec[0], vec[2], vec[3]);
- zspan_scanconvert(&bd.zspan[image_id], (void *)&bd, vec[0], vec[2], vec[3], store_bake_pixel);
- }
}
for (i = 0; i < bake_images->size; i++) {
zbuf_free_span(&bd.zspan[i]);
}
+
+ MEM_freeN(looptri);
MEM_freeN(bd.zspan);
}
@@ -718,8 +786,7 @@ void RE_bake_normal_world_to_tangent(
DerivedMesh *dm = CDDM_from_mesh(me);
- triangles = MEM_mallocN(sizeof(TriTessFace) * (me->totface * 2), "MVerts Mesh");
- mesh_calc_tri_tessface(triangles, me, true, dm);
+ triangles = mesh_calc_tri_tessface(me, true, dm);
BLI_assert(num_pixels >= 3);
@@ -749,7 +816,10 @@ void RE_bake_normal_world_to_tangent(
offset = i * depth;
if (primitive_id == -1) {
- copy_v3_fl3(&result[offset], 0.5f, 0.5f, 1.0f);
+ if (depth == 4)
+ copy_v4_fl4(&result[offset], 0.5f, 0.5f, 1.0f, 1.0f);
+ else
+ copy_v3_fl3(&result[offset], 0.5f, 0.5f, 1.0f);
continue;
}