[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [37225] trunk/blender: Bake from multires mesh

Sergey Sharybin g.ulairi at gmail.com
Sun Jun 5 22:54:04 CEST 2011


Revision: 37225
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=37225
Author:   nazgul
Date:     2011-06-05 20:54:04 +0000 (Sun, 05 Jun 2011)
Log Message:
-----------
Bake from multires mesh
=======================

Added option to baked named "Bake From Multires" which is avaliable for
normals baking and displacement baking.

If this option is enabled, then no additional hi-res meshes and render
structures would be created . This saves plenty of memory and meshes
with millions of faces could be successfully baked in few minutes.

Baking happens from highest level against viewport subdivision level,
so workflow is following:
  - Set viewport level to level at which texture would be applied
    during final rendering.
  - Choose Displacement/Normals baking.
  - Enable "Bake From Multires" option.
  - You're ready to bake.

Displacement baker had aditional option named "Low Resolution Mesh".
This option is used to set if you want texture for realtime (games)
usage.

Internally it does the following:
  - If it's disabled, displacement is calculated from subdivided
    viewport level, so texture looks "smooth" (it's how default
    baked works).
  - If it's enabled, dispalcement is calculated against unsubdivided
    viewport levels. This leads to "scales". This isn;t useful for
    offline renders much, but very useful for creating game textures.

Special thanks to Morten Mikkelsen (aka sparky) for all mathematics
and other work he've done fr this patch!

Modified Paths:
--------------
    trunk/blender/release/scripts/startup/bl_ui/properties_render.py
    trunk/blender/source/blender/blenkernel/BKE_multires.h
    trunk/blender/source/blender/blenkernel/intern/customdata.c
    trunk/blender/source/blender/blenkernel/intern/multires.c
    trunk/blender/source/blender/blenlib/BLI_math_geom.h
    trunk/blender/source/blender/blenlib/intern/math_geom.c
    trunk/blender/source/blender/editors/object/object_bake.c
    trunk/blender/source/blender/imbuf/IMB_imbuf.h
    trunk/blender/source/blender/imbuf/intern/filter.c
    trunk/blender/source/blender/makesdna/DNA_scene_types.h
    trunk/blender/source/blender/makesrna/intern/rna_scene.c
    trunk/blender/source/blender/render/intern/source/rendercore.c

Modified: trunk/blender/release/scripts/startup/bl_ui/properties_render.py
===================================================================
--- trunk/blender/release/scripts/startup/bl_ui/properties_render.py	2011-06-05 20:44:50 UTC (rev 37224)
+++ trunk/blender/release/scripts/startup/bl_ui/properties_render.py	2011-06-05 20:54:04 UTC (rev 37225)
@@ -613,29 +613,41 @@
 
         layout.prop(rd, "bake_type")
 
-        if rd.bake_type == 'NORMALS':
-            layout.prop(rd, "bake_normal_space")
-        elif rd.bake_type in {'DISPLACEMENT', 'AO'}:
-            layout.prop(rd, "use_bake_normalize")
+        multires_bake = False
+        if rd.bake_type in ['NORMALS', 'DISPLACEMENT']:
+            layout.prop(rd, 'use_bake_multires')
+            multires_bake = rd.use_bake_multires
 
-        # col.prop(rd, "bake_aa_mode")
-        # col.prop(rd, "use_bake_antialiasing")
+        if not multires_bake:
+            if rd.bake_type == 'NORMALS':
+                layout.prop(rd, "bake_normal_space")
+            elif rd.bake_type in {'DISPLACEMENT', 'AO'}:
+                layout.prop(rd, "use_bake_normalize")
 
-        layout.separator()
+            # col.prop(rd, "bake_aa_mode")
+            # col.prop(rd, "use_bake_antialiasing")
 
-        split = layout.split()
+            layout.separator()
 
-        col = split.column()
-        col.prop(rd, "use_bake_clear")
-        col.prop(rd, "bake_margin")
-        col.prop(rd, "bake_quad_split", text="Split")
+            split = layout.split()
 
-        col = split.column()
-        col.prop(rd, "use_bake_selected_to_active")
-        sub = col.column()
-        sub.active = rd.use_bake_selected_to_active
-        sub.prop(rd, "bake_distance")
-        sub.prop(rd, "bake_bias")
+            col = split.column()
+            col.prop(rd, "use_bake_clear")
+            col.prop(rd, "bake_margin")
+            col.prop(rd, "bake_quad_split", text="Split")
 
+            col = split.column()
+            col.prop(rd, "use_bake_selected_to_active")
+            sub = col.column()
+            sub.active = rd.use_bake_selected_to_active
+            sub.prop(rd, "bake_distance")
+            sub.prop(rd, "bake_bias")
+        else:
+            if rd.bake_type == 'DISPLACEMENT':
+                layout.prop(rd, "use_bake_lores_mesh")
+
+            layout.prop(rd, "use_bake_clear")
+            layout.prop(rd, "bake_margin")
+
 if __name__ == "__main__":  # only for live edit.
     bpy.utils.register_module(__name__)

Modified: trunk/blender/source/blender/blenkernel/BKE_multires.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_multires.h	2011-06-05 20:44:50 UTC (rev 37224)
+++ trunk/blender/source/blender/blenkernel/BKE_multires.h	2011-06-05 20:54:04 UTC (rev 37225)
@@ -91,6 +91,7 @@
 void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u, float v);
 void mdisp_rot_crn_to_face(const int S, const int corners, const int face_side, const float x, const float y, float *u, float *v);
 int mdisp_rot_face_to_crn(const int corners, const int face_side, const float u, const float v, float *x, float *y);
+int mdisp_rot_face_to_quad_crn(const int corners, const int face_side, const float u, const float v, float *x, float *y);
 void mdisp_apply_weight(const int S, const int corners, int x, int y, const int face_side, float crn_weight[4][2], float *u_r, float *v_r);
 void mdisp_flip_disp(const int S, const int corners, const float axis_x[2], const float axis_y[2], float disp[3]);
 void mdisp_join_tris(struct MDisps *dst, struct MDisps *tri1, struct MDisps *tri2);

Modified: trunk/blender/source/blender/blenkernel/intern/customdata.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/customdata.c	2011-06-05 20:44:50 UTC (rev 37224)
+++ trunk/blender/source/blender/blenkernel/intern/customdata.c	2011-06-05 20:54:04 UTC (rev 37225)
@@ -540,7 +540,7 @@
 				float face_u, face_v, crn_u, crn_v;
 
 				mdisp_apply_weight(S, dst_corners, x, y, st, crn_weight, &face_u, &face_v);
-				crn = mdisp_rot_face_to_crn(src_corners, st, face_u, face_v, &crn_u, &crn_v);
+				crn = mdisp_rot_face_to_quad_crn(src_corners, st, face_u, face_v, &crn_u, &crn_v);
 
 				old_mdisps_bilinear((*out), &s->disps[crn*side*side], side, crn_u, crn_v);
 				mdisp_flip_disp(crn, dst_corners, axis_x, axis_y, *out);

Modified: trunk/blender/source/blender/blenkernel/intern/multires.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/multires.c	2011-06-05 20:44:50 UTC (rev 37224)
+++ trunk/blender/source/blender/blenkernel/intern/multires.c	2011-06-05 20:54:04 UTC (rev 37225)
@@ -1997,6 +1997,7 @@
 	}
 }
 
+/* Find per-corner coordinate with given per-face UV coord */
 int mdisp_rot_face_to_crn(const int corners, const int face_side, const float u, const float v, float *x, float *y)
 {
 	const float offset = face_side*0.5f - 0.5f;
@@ -2022,6 +2023,61 @@
 			*y = v - offset;
 		}
 	} else {
+		int grid_size = offset;
+		float w = (face_side - 1) - u - v;
+		float W1, W2;
+
+		if (u >= v && u >= w) {S = 0; W1= w; W2= v;}
+		else if (v >= u && v >= w) {S = 1; W1 = u; W2 = w;}
+		else {S = 2; W1 = v; W2 = u;}
+
+		W1 /= (face_side-1);
+		W2 /= (face_side-1);
+
+		*x = (1-(2*W1)/(1-W2)) * grid_size;
+		*y = (1-(2*W2)/(1-W1)) * grid_size;
+	}
+
+	return S;
+}
+
+/* Find per-corner coordinate with given per-face UV coord
+   Practically as the previous funciton but it assumes a bit different coordinate system for triangles
+   which is optimized for MDISP layer interpolation:
+
+   v
+   ^
+   |      /|
+   |    /  |
+   |  /    |
+   |/______|___> u
+
+ */
+int mdisp_rot_face_to_quad_crn(const int corners, const int face_side, const float u, const float v, float *x, float *y)
+{
+	const float offset = face_side*0.5f - 0.5f;
+	int S = 0;
+
+	if (corners == 4) {
+		if(u <= offset && v <= offset) S = 0;
+		else if(u > offset  && v <= offset) S = 1;
+		else if(u > offset  && v > offset) S = 2;
+		else if(u <= offset && v >= offset)  S = 3;
+
+		if(S == 0) {
+			*y = offset - u;
+			*x = offset - v;
+		} else if(S == 1) {
+			*x = u - offset;
+			*y = offset - v;
+		} else if(S == 2) {
+			*y = u - offset;
+			*x = v - offset;
+		} else if(S == 3) {
+			*x= offset - u;
+			*y = v - offset;
+		}
+	} else {
 		float crn[3][4][2];
 		float p[2] = {u, v};
 
@@ -2148,7 +2204,7 @@
 					face_v = st - 1 - face_v;
 				} else src = tri1;
 
-				crn = mdisp_rot_face_to_crn(3, st, face_u, face_v, &crn_u, &crn_v);
+				crn = mdisp_rot_face_to_quad_crn(3, st, face_u, face_v, &crn_u, &crn_v);
 
 				old_mdisps_bilinear((*out), &src->disps[crn*side*side], side, crn_u, crn_v);
 				(*out)[0] = 0;

Modified: trunk/blender/source/blender/blenlib/BLI_math_geom.h
===================================================================
--- trunk/blender/source/blender/blenlib/BLI_math_geom.h	2011-06-05 20:44:50 UTC (rev 37224)
+++ trunk/blender/source/blender/blenlib/BLI_math_geom.h	2011-06-05 20:54:04 UTC (rev 37225)
@@ -162,6 +162,9 @@
 void barycentric_weights_v2(const float v1[2], const float v2[2], const float v3[2],
 	const float co[2], float w[3]);
 
+void resolve_tri_uv(float uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2]);
+void resolve_quad_uv(float uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2]);
+
 /***************************** View & Projection *****************************/
 
 void lookat_m4(float mat[4][4], float vx, float vy, 

Modified: trunk/blender/source/blender/blenlib/intern/math_geom.c
===================================================================
--- trunk/blender/source/blender/blenlib/intern/math_geom.c	2011-06-05 20:44:50 UTC (rev 37224)
+++ trunk/blender/source/blender/blenlib/intern/math_geom.c	2011-06-05 20:54:04 UTC (rev 37225)
@@ -1809,6 +1809,80 @@
 	v[2]= 3*a[2]*t2 + 2*b[2]*t + v1[2];
 }
 
+/* unfortunately internal calculations have to be done at double precision to achieve correct/stable results. */
+
+#define IS_ZERO(x) ((x>(-DBL_EPSILON) && x<DBL_EPSILON) ? 1 : 0)
+
+/* Barycentric reverse  */
+void resolve_tri_uv(float uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2])
+{
+	/* find UV such that
+	   t= u*t0 + v*t1 + (1-u-v)*t2
+	   u*(t0-t2) + v*(t1-t2)= t-t2 */
+	const double a= st0[0]-st2[0], b= st1[0]-st2[0];
+	const double c= st0[1]-st2[1], d= st1[1]-st2[1];
+	const double det= a*d - c*b;
+
+	if(IS_ZERO(det)==0)	{  /* det should never be zero since the determinant is the signed ST area of the triangle. */
+		const double x[]= {st[0]-st2[0], st[1]-st2[1]};
+
+		uv[0]= (float)((d*x[0] - b*x[1])/det);
+		uv[1]= (float)(((-c)*x[0] + a*x[1])/det);
+	} else zero_v2(uv);
+}
+
+/* bilinear reverse */
+void resolve_quad_uv(float uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2])
+{
+	const double signed_area= (st0[0]*st1[1] - st0[1]*st1[0]) + (st1[0]*st2[1] - st1[1]*st2[0]) +
+                              (st2[0]*st3[1] - st2[1]*st3[0]) + (st3[0]*st0[1] - st3[1]*st0[0]);
+
+	/* X is 2D cross product (determinant)
+	   A= (p0-p) X (p0-p3)*/
+	const double a= (st0[0]-st[0])*(st0[1]-st3[1]) - (st0[1]-st[1])*(st0[0]-st3[0]);
+
+	/* B= ( (p0-p) X (p1-p2) + (p1-p) X (p0-p3) ) / 2 */
+	const double b= 0.5 * ( ((st0[0]-st[0])*(st1[1]-st2[1]) - (st0[1]-st[1])*(st1[0]-st2[0])) +
+							 ((st1[0]-st[0])*(st0[1]-st3[1]) - (st1[1]-st[1])*(st0[0]-st3[0])) );
+
+	/* C = (p1-p) X (p1-p2) */
+	const double fC= (st1[0]-st[0])*(st1[1]-st2[1]) - (st1[1]-st[1])*(st1[0]-st2[0]);
+	const double denom= a - 2*b + fC;
+
+	// clear outputs
+	zero_v2(uv);
+
+	if(IS_ZERO(denom)!=0) {
+		const double fDen= a-fC;
+		if(IS_ZERO(fDen)==0)
+			uv[0]= (float)(a / fDen);
+	} else {
+		const double desc_sq= b*b - a*fC;
+		const double desc= sqrt(desc_sq<0.0?0.0:desc_sq);
+		const double s= signed_area>0 ? (-1.0) : 1.0;
+
+		uv[0]= (float)(( (a-b) + s * desc ) / denom);
+	}
+
+	/* find UV such that
+	  fST = (1-u)(1-v)*ST0 + u*(1-v)*ST1 + u*v*ST2 + (1-u)*v*ST3 */
+	{
+		const double denom_s= (1-uv[0])*(st0[0]-st3[0]) + uv[0]*(st1[0]-st2[0]);
+		const double denom_t= (1-uv[0])*(st0[1]-st3[1]) + uv[0]*(st1[1]-st2[1]);
+		int i= 0; double denom= denom_s;
+
+		if(fabs(denom_s)<fabs(denom_t)) {
+			i= 1;
+			denom=denom_t;
+		}
+

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list