Ok. I took the respective code from blender as below. Still I am getting some exception. Will troubleshoot and see.
inline int max_ii(int a, int b)
{
return (b < a) ? a : b;
}
inline float min_ff(float a, float b)
{
return (a < b) ? a : b;
}
inline int min_ii(int a, int b)
{
return (a < b) ? a : b;
}
inline float max_ff(float a, float b)
{
return (a > b) ? a : b;
}
static void bake_differentials(BakeDataZSpan *bd,
const float *uv1,
const float *uv2,
const float *uv3)
{
float A;
/* assumes dPdu = P1 - P3 and dPdv = P2 - P3 */
A = (uv2[0] - uv1[0]) * (uv3[1] - uv1[1]) - (uv3[0] - uv1[0]) * (uv2[1] - uv1[1]);
if (fabsf(A) > FLT_EPSILON) {
A = 0.5f / A;
bd->du_dx = (uv2[1] - uv3[1]) * A;
bd->dv_dx = (uv3[1] - uv1[1]) * A;
bd->du_dy = (uv3[0] - uv2[0]) * A;
bd->dv_dy = (uv1[0] - uv3[0]) * A;
}
else {
bd->du_dx = bd->du_dy = 0.0f;
bd->dv_dx = bd->dv_dy = 0.0f;
}
}
static void zbuf_add_to_span(ZSpan *zspan, const float v1[2], const float v2[2])
{
const float *minv, *maxv;
float *span;
float xx1, dx0, xs0;
int y, my0, my2;
if (v1[1] < v2[1]) {
minv = v1;
maxv = v2;
}
else {
minv = v2;
maxv = v1;
}
my0 = ceil(minv[1]);
my2 = floor(maxv[1]);
if (my2 < 0 || my0 >= zspan->recty) {
return;
}
/* clip top */
if (my2 >= zspan->recty) {
my2 = zspan->recty - 1;
}
/* clip bottom */
if (my0 < 0) {
my0 = 0;
}
if (my0 > my2) {
return;
}
/* if (my0>my2) should still fill in, that way we get spans that skip nicely */
xx1 = maxv[1] - minv[1];
if (xx1 > FLT_EPSILON) {
dx0 = (minv[0] - maxv[0]) / xx1;
xs0 = dx0 * (minv[1] - my2) + minv[0];
}
else {
dx0 = 0.0f;
xs0 = min_ff(minv[0], maxv[0]);
}
/* empty span */
if (zspan->maxp1 == NULL) {
span = zspan->span1;
}
else { /* does it complete left span? */
if (maxv == zspan->minp1 || minv == zspan->maxp1) {
span = zspan->span1;
}
else {
span = zspan->span2;
}
}
if (span == zspan->span1) {
// printf("left span my0 %d my2 %d\n", my0, my2);
if (zspan->minp1 == NULL || zspan->minp1[1] > minv[1]) {
zspan->minp1 = minv;
}
if (zspan->maxp1 == NULL || zspan->maxp1[1] < maxv[1]) {
zspan->maxp1 = maxv;
}
if (my0 < zspan->miny1) {
zspan->miny1 = my0;
}
if (my2 > zspan->maxy1) {
zspan->maxy1 = my2;
}
}
else {
// printf("right span my0 %d my2 %d\n", my0, my2);
if (zspan->minp2 == NULL || zspan->minp2[1] > minv[1]) {
zspan->minp2 = minv;
}
if (zspan->maxp2 == NULL || zspan->maxp2[1] < maxv[1]) {
zspan->maxp2 = maxv;
}
if (my0 < zspan->miny2) {
zspan->miny2 = my0;
}
if (my2 > zspan->maxy2) {
zspan->maxy2 = my2;
}
}
for (y = my2; y >= my0; y--, xs0 += dx0) {
/* xs0 is the xcoord! */
span[y] = xs0;
}
}
/* reset range for clipping */
static void zbuf_init_span(ZSpan *zspan)
{
zspan->miny1 = zspan->miny2 = zspan->recty + 1;
zspan->maxy1 = zspan->maxy2 = -1;
zspan->minp1 = zspan->maxp1 = zspan->minp2 = zspan->maxp2 = NULL;
}
/* Scanconvert for strand triangles, calls func for each x, y coordinate
* and gives UV barycentrics and z. */
void zspan_scanconvert(ZSpan *zspan,
BakeDataZSpan *handle,
float *v1,
float *v2,
float *v3,
void (*func)(BakeDataZSpan *, int, int, float, float))
{
float x0, y0, x1, y1, x2, y2, z0, z1, z2;
float u, v, uxd, uyd, vxd, vyd, uy0, vy0, xx1;
const float *span1, *span2;
int i, j, x, y, sn1, sn2, rectx = zspan->rectx, my0, my2;
/* init */
zbuf_init_span(zspan);
/* set spans */
zbuf_add_to_span(zspan, v1, v2);
zbuf_add_to_span(zspan, v2, v3);
zbuf_add_to_span(zspan, v3, v1);
/* clipped */
if (zspan->minp2 == NULL || zspan->maxp2 == NULL) {
return;
}
my0 = max_ii(zspan->miny1, zspan->miny2);
my2 = min_ii(zspan->maxy1, zspan->maxy2);
// printf("my %d %d\n", my0, my2);
if (my2 < my0) {
return;
}
/* ZBUF DX DY, in floats still */
x1 = v1[0] - v2[0];
x2 = v2[0] - v3[0];
y1 = v1[1] - v2[1];
y2 = v2[1] - v3[1];
z1 = 1.0f; /* (u1 - u2) */
z2 = 0.0f; /* (u2 - u3) */
x0 = y1 * z2 - z1 * y2;
y0 = z1 * x2 - x1 * z2;
z0 = x1 * y2 - y1 * x2;
if (z0 == 0.0f) {
return;
}
xx1 = (x0 * v1[0] + y0 * v1[1]) / z0 + 1.0f;
uxd = -(double)x0 / (double)z0;
uyd = -(double)y0 / (double)z0;
uy0 = ((double)my2) * uyd + (double)xx1;
z1 = -1.0f; /* (v1 - v2) */
z2 = 1.0f; /* (v2 - v3) */
x0 = y1 * z2 - z1 * y2;
y0 = z1 * x2 - x1 * z2;
xx1 = (x0 * v1[0] + y0 * v1[1]) / z0;
vxd = -(double)x0 / (double)z0;
vyd = -(double)y0 / (double)z0;
vy0 = ((double)my2) * vyd + (double)xx1;
/* correct span */
span1 = zspan->span1 + my2;
span2 = zspan->span2 + my2;
for (i = 0, y = my2; y >= my0; i++, y--, span1--, span2--) {
sn1 = floor(min_ff(*span1, *span2));
sn2 = floor(max_ff(*span1, *span2));
sn1++;
if (sn2 >= rectx) {
sn2 = rectx - 1;
}
if (sn1 < 0) {
sn1 = 0;
}
u = (((double)sn1 * uxd) + uy0) - (i * uyd);
v = (((double)sn1 * vxd) + vy0) - (i * vyd);
for (j = 0, x = sn1; x <= sn2; j++, x++) {
func(handle, x, y, u + (j * uxd), v + (j * vxd));
}
}
}
inline void copy_v2_fl2(float v[2], float x, float y)
{
v[0] = x;
v[1] = y;
}
static void store_bake_pixel(BakeDataZSpan *handle, int x, int y, float u, float v)
{
BakeDataZSpan *bd = (BakeDataZSpan *)handle;
BakePixel *pixel;
const int width = bd->bk_image->width;
const size_t offset = bd->bk_image->offset;
const int i = offset + y * width + x;
pixel = &bd->pixel_array[i];
pixel->primitive_id = bd->primitive_id;
/* At this point object_id is always 0, since this function runs for the
* low-poly mesh only. The object_id lookup indices are set afterwards. */
copy_v2_fl2(pixel->uv, u, v);
pixel->du_dx = bd->du_dx;
pixel->du_dy = bd->du_dy;
pixel->dv_dx = bd->dv_dx;
pixel->dv_dy = bd->dv_dy;
pixel->object_id = 0;
}
/* each zbuffer has coordinates transformed to local rect coordinates, so we can simply clip */
void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty)
{
memset(zspan, 0, sizeof(ZSpan));
zspan->rectx = rectx;
zspan->recty = recty;
zspan->span1 = (float *)malloc(recty * sizeof(float));
zspan->span2 = (float *)malloc(recty * sizeof(float));
}
void populate_bake_data(
const Mesh &mesh, size_t uv_map_index, size_t image_width, size_t image_height, BakeData *data)
{
size_t num_pixels = image_width * image_height;
BakePixel *pixel_array = (BakePixel *)malloc(sizeof(BakePixel) * num_pixels);
/* initialize all pixel arrays so we know which ones are 'blank' */
BakeDataZSpan *bd = new BakeDataZSpan();
bd->bk_image = new BakeImage();
bd->bk_image->width = image_width;
bd->bk_image->height = image_height;
bd->bk_image->offset = 0;
bd->pixel_array = pixel_array;
bd->zspan = new ZSpan();
for (size_t i = 0; i < num_pixels; i++) {
pixel_array[i].primitive_id = -1;
pixel_array[i].object_id = 0;
}
zbuf_alloc_span(bd->zspan, image_width, image_height);
/*ZSpan zspan;
zspan.rectx = image_width;
zspan.recty = image_height;*/
Attribute *attributes = mesh.attributes.find(AttributeStandard::ATTR_STD_UV);
float2 *fdata = attributes[uv_map_index].data_float2();
size_t triangles_count = mesh.num_triangles();
for (size_t i = 0; i < triangles_count; i++) {
bd->primitive_id = i;
float vec[3][2];
Mesh::Triangle triangle = mesh.get_triangle(i);
/* array<float3> p1 = mesh.verts[triangle.v[0]];
array<float3> p2 = mesh.verts[triangle.v[1]];
array<float3> p3 = mesh.verts[triangle.v[2]];*/
for (size_t j = 0; j < 3; j++) {
float2 uv = fdata[triangle.v[j]];
vec[j][0] = uv[0] * (float)image_width - (0.5f + 0.001f);
vec[j][1] = uv[1] * (float)image_height - (0.5f + 0.002f);
}
bake_differentials(bd, vec[0], vec[1], vec[2]);
zspan_scanconvert(bd->zspan, bd, vec[0], vec[1], vec[2], store_bake_pixel);
}
BakePixel *bp = pixel_array;
for (size_t i = 0; i < num_pixels; i++) {
data->set(i, bp->primitive_id, bp->uv, bp->du_dx, bp->du_dy, bp->dv_dx, bp->dv_dy);
bp++;
}