Changeset View
Changeset View
Standalone View
Standalone View
source/blender/render/intern/source/bake_api.c
| Show All 32 Lines | |||||
| * ``def bake(scene, object, pass_type, object_id, pixel_array, num_pixels, depth, result)`` | * ``def bake(scene, object, pass_type, object_id, pixel_array, num_pixels, depth, result)`` | ||||
| * - scene: current scene (Python object) | * - scene: current scene (Python object) | ||||
| * - object: object to render (Python object) | * - object: object to render (Python object) | ||||
| * - pass_type: pass to render (string, e.g., "COMBINED", "AO", "NORMAL", ...) | * - pass_type: pass to render (string, e.g., "COMBINED", "AO", "NORMAL", ...) | ||||
| * - object_id: index of object to bake (to use with the pixel_array) | * - object_id: index of object to bake (to use with the pixel_array) | ||||
| * - pixel_array: list of primitive ids and barycentric coordinates to bake(Python object, see bake_pixel) | * - pixel_array: list of primitive ids and barycentric coordinates to bake(Python object, see bake_pixel) | ||||
| * - num_pixels: size of pixel_array, number of pixels to bake (int) | * - num_pixels: size of pixel_array, number of pixels to bake (int) | ||||
| * - depth: depth of pixels to return (int, assuming always 4 now) | * - depth: depth of pixels to return (int, assuming always 4 now) | ||||
| * - matrix: transformation matrix relative to the object (for dupli objects), for regular objects use an identity matrix or NULL | |||||
| * - result: array to be populated by the engine (float array, PyLong_AsVoidPtr) | * - result: array to be populated by the engine (float array, PyLong_AsVoidPtr) | ||||
| * | * | ||||
| * \note Normals are expected to be in World Space and in the +X, +Y, +Z orientation. | * \note Normals are expected to be in World Space and in the +X, +Y, +Z orientation. | ||||
| * | * | ||||
| * \subsection bake_pixel BakePixel data structure | * \subsection bake_pixel BakePixel data structure | ||||
| * | * | ||||
| * pixel_array is a Python object storing BakePixel elements: | * pixel_array is a Python object storing BakePixel elements: | ||||
| * | * | ||||
| ▲ Show 20 Lines • Show All 237 Lines • ▼ Show 20 Lines | static bool cast_ray_highpoly( | ||||
| int hit_mesh = -1; | int hit_mesh = -1; | ||||
| float hit_distance = FLT_MAX; | float hit_distance = FLT_MAX; | ||||
| BVHTreeRayHit *hits; | BVHTreeRayHit *hits; | ||||
| hits = MEM_mallocN(sizeof(BVHTreeRayHit) * tot_highpoly, "Bake Highpoly to Lowpoly: BVH Rays"); | hits = MEM_mallocN(sizeof(BVHTreeRayHit) * tot_highpoly, "Bake Highpoly to Lowpoly: BVH Rays"); | ||||
| for (i = 0; i < tot_highpoly; i++) { | for (i = 0; i < tot_highpoly; i++) { | ||||
| float co_high[3], dir_high[3]; | float co_high[3], dir_high[3]; | ||||
| int mesh_id = highpoly[i].mesh_lookup_id; | |||||
| hits[i].index = -1; | hits[i].index = -1; | ||||
| /* TODO: we should use FLT_MAX here, but sweepsphere code isn't prepared for that */ | /* TODO: we should use FLT_MAX here, but sweepsphere code isn't prepared for that */ | ||||
| hits[i].dist = 10000.0f; | hits[i].dist = 10000.0f; | ||||
| /* transform the ray from the world space to the highpoly space */ | /* transform the ray from the world space to the highpoly space */ | ||||
| mul_v3_m4v3(co_high, highpoly[i].imat, co); | mul_v3_m4v3(co_high, highpoly[i].imat, co); | ||||
| /* rotates */ | /* rotates */ | ||||
| mul_v3_mat3_m4v3(dir_high, highpoly[i].imat, dir); | mul_v3_mat3_m4v3(dir_high, highpoly[i].imat, dir); | ||||
| normalize_v3(dir_high); | normalize_v3(dir_high); | ||||
| /* cast ray */ | /* cast ray */ | ||||
| if (treeData[i].tree) { | if (treeData[mesh_id].tree) { | ||||
| BLI_bvhtree_ray_cast(treeData[i].tree, co_high, dir_high, 0.0f, &hits[i], treeData[i].raycast_callback, &treeData[i]); | BLI_bvhtree_ray_cast(treeData[mesh_id].tree, co_high, dir_high, 0.0f, &hits[i], treeData[mesh_id].raycast_callback, &treeData[mesh_id]); | ||||
| } | } | ||||
| if (hits[i].index != -1) { | if (hits[i].index != -1) { | ||||
| /* cull backface */ | /* cull backface */ | ||||
| const float dot = dot_v3v3(dir_high, hits[i].no); | const float dot = dot_v3v3(dir_high, hits[i].no); | ||||
| if (dot < 0.0f) { | if (dot < 0.0f) { | ||||
| float distance; | float distance; | ||||
| float hit_world[3]; | float hit_world[3]; | ||||
| /* distance comparison in world space */ | /* distance comparison in world space */ | ||||
| mul_v3_m4v3(hit_world, highpoly[i].obmat, hits[i].co); | mul_v3_m4v3(hit_world, highpoly[i].obmat, hits[i].co); | ||||
| distance = len_squared_v3v3(hit_world, co); | distance = len_squared_v3v3(hit_world, co); | ||||
| if (distance < hit_distance) { | if (distance < hit_distance) { | ||||
| hit_mesh = i; | hit_mesh = i; | ||||
| hit_distance = distance; | hit_distance = distance; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (hit_mesh != -1) { | if (hit_mesh != -1) { | ||||
| calc_barycentric_from_point(triangles[hit_mesh], hits[hit_mesh].index, hits[hit_mesh].co, &primitive_id, uv); | calc_barycentric_from_point(triangles[highpoly[hit_mesh].mesh_lookup_id], hits[hit_mesh].index, hits[hit_mesh].co, &primitive_id, uv); | ||||
| pixel_array[pixel_id].primitive_id = primitive_id; | pixel_array[pixel_id].primitive_id = primitive_id; | ||||
| pixel_array[pixel_id].object_id = hit_mesh; | pixel_array[pixel_id].object_id = hit_mesh; | ||||
| copy_v2_v2(pixel_array[pixel_id].uv, uv); | copy_v2_v2(pixel_array[pixel_id].uv, uv); | ||||
| /* the differentials are relative to the UV/image space, so the highpoly differentials | /* the differentials are relative to the UV/image space, so the highpoly differentials | ||||
| * are the same as the low poly differentials */ | * are the same as the low poly differentials */ | ||||
| pixel_array[pixel_id].du_dx = du_dx; | pixel_array[pixel_id].du_dx = du_dx; | ||||
| pixel_array[pixel_id].du_dy = du_dy; | pixel_array[pixel_id].du_dy = du_dy; | ||||
| ▲ Show 20 Lines • Show All 98 Lines • ▼ Show 20 Lines | for (i = 0; i < me->totface; i++) { | ||||
| } | } | ||||
| } | } | ||||
| BLI_assert(p_id < me->totface * 2); | BLI_assert(p_id < me->totface * 2); | ||||
| } | } | ||||
| bool RE_bake_pixels_populate_from_objects( | bool RE_bake_pixels_populate_from_objects( | ||||
| struct Mesh *me_low, BakePixel pixel_array_from[], BakePixel pixel_array_to[], | struct Mesh *me_low, BakePixel pixel_array_from[], BakePixel pixel_array_to[], | ||||
| BakeHighPolyData highpoly[], const int tot_highpoly, const size_t num_pixels, const bool is_custom_cage, | BakeHighPolyMesh **highpoly_meshes, const int tot_highpoly_meshes, | ||||
| BakeHighPolyData highpoly_objects[], const int tot_highpoly_objects, | |||||
| const size_t num_pixels, const bool is_custom_cage, | |||||
| const float cage_extrusion, float mat_low[4][4], float mat_cage[4][4], struct Mesh *me_cage) | const float cage_extrusion, float mat_low[4][4], float mat_cage[4][4], struct Mesh *me_cage) | ||||
| { | { | ||||
| size_t i; | size_t i; | ||||
| int primitive_id; | int primitive_id; | ||||
| float u, v; | float u, v; | ||||
| float imat_low[4][4]; | float imat_low[4][4]; | ||||
| bool is_cage = me_cage != NULL; | bool is_cage = me_cage != NULL; | ||||
| bool result = true; | bool result = true; | ||||
| DerivedMesh *dm_low = NULL; | DerivedMesh *dm_low = NULL; | ||||
| DerivedMesh **dm_highpoly; | DerivedMesh **dm_highpoly; | ||||
| BVHTreeFromMesh *treeData; | BVHTreeFromMesh *treeData; | ||||
| /* Note: all coordinates are in local space */ | /* Note: all coordinates are in local space */ | ||||
| TriTessFace *tris_low = NULL; | TriTessFace *tris_low = NULL; | ||||
| TriTessFace *tris_cage = NULL; | TriTessFace *tris_cage = NULL; | ||||
| TriTessFace **tris_high; | TriTessFace **tris_high; | ||||
| /* assume all lowpoly tessfaces can be quads */ | /* assume all lowpoly tessfaces can be quads */ | ||||
| tris_high = MEM_callocN(sizeof(TriTessFace *) * tot_highpoly, "MVerts Highpoly Mesh Array"); | tris_high = MEM_callocN(sizeof(TriTessFace *) * tot_highpoly_meshes, "MVerts Highpoly Mesh Array"); | ||||
| /* assume all highpoly tessfaces are triangles */ | /* assume all highpoly tessfaces are triangles */ | ||||
| dm_highpoly = MEM_mallocN(sizeof(DerivedMesh *) * tot_highpoly, "Highpoly Derived Meshes"); | dm_highpoly = MEM_mallocN(sizeof(DerivedMesh *) * tot_highpoly_meshes, "Highpoly Derived Meshes"); | ||||
| treeData = MEM_callocN(sizeof(BVHTreeFromMesh) * tot_highpoly, "Highpoly BVH Trees"); | treeData = MEM_callocN(sizeof(BVHTreeFromMesh) * tot_highpoly_meshes, "Highpoly BVH Trees"); | ||||
| if (!is_cage) { | if (!is_cage) { | ||||
| dm_low = CDDM_from_mesh(me_low); | dm_low = CDDM_from_mesh(me_low); | ||||
| tris_low = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Lowpoly Mesh"); | tris_low = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Lowpoly Mesh"); | ||||
| mesh_calc_tri_tessface(tris_low, me_low, true, dm_low); | mesh_calc_tri_tessface(tris_low, me_low, true, dm_low); | ||||
| } | } | ||||
| else if (is_custom_cage) { | else if (is_custom_cage) { | ||||
| tris_low = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Lowpoly Mesh"); | tris_low = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Lowpoly Mesh"); | ||||
| mesh_calc_tri_tessface(tris_low, me_low, false, NULL); | mesh_calc_tri_tessface(tris_low, me_low, false, NULL); | ||||
| tris_cage = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Cage Mesh"); | tris_cage = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Cage Mesh"); | ||||
| mesh_calc_tri_tessface(tris_cage, me_cage, false, NULL); | mesh_calc_tri_tessface(tris_cage, me_cage, false, NULL); | ||||
| } | } | ||||
| else { | else { | ||||
| tris_cage = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Cage Mesh"); | tris_cage = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Cage Mesh"); | ||||
| mesh_calc_tri_tessface(tris_cage, me_cage, false, NULL); | mesh_calc_tri_tessface(tris_cage, me_cage, false, NULL); | ||||
| } | } | ||||
| invert_m4_m4(imat_low, mat_low); | invert_m4_m4(imat_low, mat_low); | ||||
| for (i = 0; i < tot_highpoly; i++) { | for (i = 0; i < tot_highpoly_meshes; i++) { | ||||
| tris_high[i] = MEM_mallocN(sizeof(TriTessFace) * highpoly[i].me->totface, "MVerts Highpoly Mesh"); | tris_high[i] = MEM_mallocN(sizeof(TriTessFace) * highpoly_meshes[i]->me->totface, "MVerts Highpoly Mesh"); | ||||
| mesh_calc_tri_tessface(tris_high[i], highpoly[i].me, false, NULL); | mesh_calc_tri_tessface(tris_high[i], highpoly_meshes[i]->me, false, NULL); | ||||
| dm_highpoly[i] = CDDM_from_mesh(highpoly[i].me); | dm_highpoly[i] = CDDM_from_mesh(highpoly_meshes[i]->me); | ||||
| if (dm_highpoly[i]->getNumTessFaces(dm_highpoly[i]) != 0) { | if (dm_highpoly[i]->getNumTessFaces(dm_highpoly[i]) != 0) { | ||||
| /* Create a bvh-tree for each highpoly object */ | /* Create a bvh-tree for each highpoly object */ | ||||
| bvhtree_from_mesh_faces(&treeData[i], dm_highpoly[i], 0.0, 2, 6); | bvhtree_from_mesh_faces(&treeData[i], dm_highpoly[i], 0.0, 2, 6); | ||||
| if (treeData[i].tree == NULL) { | if (treeData[i].tree == NULL) { | ||||
| printf("Baking: out of memory while creating BHVTree for object \"%s\"\n", highpoly[i].ob->id.name + 2); | printf("Baking: out of memory while creating BHVTree for object \"%s\"\n", highpoly_meshes[i]->ob->id.name + 2); | ||||
| result = false; | result = false; | ||||
| goto cleanup; | goto cleanup; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| for (i = 0; i < num_pixels; i++) { | for (i = 0; i < num_pixels; i++) { | ||||
| float co[3]; | float co[3]; | ||||
| Show All 16 Lines | for (i = 0; i < num_pixels; i++) { | ||||
| else if (is_cage) { | else if (is_cage) { | ||||
| calc_point_from_barycentric_extrusion(tris_cage, mat_low, imat_low, primitive_id, u, v, cage_extrusion, co, dir, true); | calc_point_from_barycentric_extrusion(tris_cage, mat_low, imat_low, primitive_id, u, v, cage_extrusion, co, dir, true); | ||||
| } | } | ||||
| else { | else { | ||||
| calc_point_from_barycentric_extrusion(tris_low, mat_low, imat_low, primitive_id, u, v, cage_extrusion, co, dir, false); | calc_point_from_barycentric_extrusion(tris_low, mat_low, imat_low, primitive_id, u, v, cage_extrusion, co, dir, false); | ||||
| } | } | ||||
| /* cast ray */ | /* cast ray */ | ||||
| if (!cast_ray_highpoly(treeData, tris_high, pixel_array_to, highpoly, co, dir, i, tot_highpoly, | if (!cast_ray_highpoly(treeData, tris_high, pixel_array_to, highpoly_objects, | ||||
| co, dir, i, tot_highpoly_objects, | |||||
| pixel_array_from[i].du_dx, pixel_array_from[i].du_dy, | pixel_array_from[i].du_dx, pixel_array_from[i].du_dy, | ||||
| pixel_array_from[i].dv_dx, pixel_array_from[i].dv_dy)) { | pixel_array_from[i].dv_dx, pixel_array_from[i].dv_dy)) { | ||||
| /* if it fails mask out the original pixel array */ | /* if it fails mask out the original pixel array */ | ||||
| pixel_array_from[i].primitive_id = -1; | pixel_array_from[i].primitive_id = -1; | ||||
| } | } | ||||
| } | } | ||||
| /* garbage collection */ | /* garbage collection */ | ||||
| cleanup: | cleanup: | ||||
| for (i = 0; i < tot_highpoly; i++) { | for (i = 0; i < tot_highpoly_meshes; i++) { | ||||
| free_bvhtree_from_mesh(&treeData[i]); | free_bvhtree_from_mesh(&treeData[i]); | ||||
| if (dm_highpoly[i]) { | if (dm_highpoly[i]) { | ||||
| dm_highpoly[i]->release(dm_highpoly[i]); | dm_highpoly[i]->release(dm_highpoly[i]); | ||||
| } | } | ||||
| if (tris_high[i]) { | if (tris_high[i]) { | ||||
| MEM_freeN(tris_high[i]); | MEM_freeN(tris_high[i]); | ||||
| ▲ Show 20 Lines • Show All 438 Lines • Show Last 20 Lines | |||||