[Bf-blender-cvs] [7a75489] soc-2014-nurbs: Putting it all together: {BSpline, NURBS} values+derivates calculate & verify with Mathematica, smooth normals display properly.

Jonathan deWerd noreply at git.blender.org
Sat Jul 26 20:47:55 CEST 2014


Commit: 7a75489f86d5892788626fb3da759b7ef6c053e9
Author: Jonathan deWerd
Date:   Wed Jul 23 23:50:32 2014 -0400
Branches: soc-2014-nurbs
https://developer.blender.org/rB7a75489f86d5892788626fb3da759b7ef6c053e9

Putting it all together: {BSpline,NURBS} values+derivates calculate & verify with Mathematica, smooth normals display properly.

===================================================================

M	source/blender/blenkernel/BKE_curve.h
M	source/blender/blenkernel/BKE_displist.h
M	source/blender/blenkernel/intern/curve.cpp
M	source/blender/blenkernel/intern/curve_eval.cpp
M	source/blender/blenkernel/intern/displist.c
M	source/blender/editors/space_view3d/drawobject.c
M	tests/interactive/curve_eval.h
M	tests/interactive/nurbs_derivative_eval.cpp
M	tests/interactive/nurbs_eval.nb

===================================================================

diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 378e3c0..f689175 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -47,6 +47,7 @@ struct Path;
 struct TextBox;
 struct rctf;
 struct DispList;
+typedef struct BPoint BPoint;
 
 typedef struct CurveCache {
 	ListBase disp;
@@ -56,6 +57,12 @@ typedef struct CurveCache {
 
 #define NURBS_MAX_ORDER 10
 
+typedef struct BSplineCache {
+	float u;
+	int iu;
+	float Nu[NURBS_MAX_ORDER][NURBS_MAX_ORDER];
+} BSplineCacheU;
+
 #define KNOTSU(nu)      ( (nu)->orderu + (nu)->pntsu + (((nu)->flagu & CU_NURB_CYCLIC) ? ((nu)->orderu - 1) : 0) )
 #define KNOTSV(nu)      ( (nu)->orderv + (nu)->pntsv + (((nu)->flagv & CU_NURB_CYCLIC) ? ((nu)->orderv - 1) : 0) )
 
@@ -123,8 +130,28 @@ void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float
 void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *tb, struct rctf *r_rect);
 
 /* ** Nurbs ** */
+#ifdef __cplusplus
+#define DEFAULT_FALSE =false
+#define DEFAULT_NULL =NULL
+#else
+#define DEFAULT_FALSE
+#define DEFAULT_NULL
+#endif
+void BKE_bspline_knot_calc(int flags, int pnts, int order, float knots[]);
 int BKE_bspline_nz_basis_range(float u, float *knots, int num_pts, int order);
-void BKE_bspline_basis_eval(float u, int i, float *U, int num_pts, int order, int nd, float out[][NURBS_MAX_ORDER]);
+void BKE_bspline_basis_eval(float u, int i, float *U, int num_knots, int order, int nd, float out[][NURBS_MAX_ORDER]);
+void BKE_bspline_curve_eval(float u, float *U, int num_pts, int order, BPoint *P, int stride, int nd, BPoint *out, bool premultiply_weight DEFAULT_FALSE);
+void BKE_nurbs_curve_eval(float u, float *U, int num_pts, int order, BPoint *P, int stride, int nd, BPoint *out);
+void BKE_bspline_surf_eval(float u, float v,
+						   int pntsu, int orderu, float *U,
+						   int pntsv, int orderv, float *V,
+						   BPoint *P, int nd, BPoint *out,
+						   bool premultiply_weights DEFAULT_FALSE, BSplineCacheU *ucache DEFAULT_NULL);
+void BKE_nurbs_surf_eval(float u, float v,
+						 int pntsu, int orderu, float *U,
+						 int pntsv, int orderv, float *V,
+						 BPoint *P, int nd, BPoint *out, BSplineCacheU *ucache DEFAULT_NULL);
+
 
 bool BKE_nurbList_index_get_co(struct ListBase *editnurb, const int index, float r_co[3]);
 
@@ -149,7 +176,6 @@ void BKE_nurb_minmax(struct Nurb *nu, bool use_radius, float min[3], float max[3
 void BKE_nurb_makeFaces(struct Nurb *nu, float *coord_array, int rowstride, int resolu, int resolv);
 void BKE_nurb_makeCurve(struct Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, float *weight_array, int resolu, int stride);
 
-void BKE_nurb_knot_calc(int flags, int pnts, int order, float knots[]);
 void BKE_nurb_knot_calc_u(struct Nurb *nu);
 void BKE_nurb_knot_calc_v(struct Nurb *nu);
 
diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h
index 0afc457..bcda5e8 100644
--- a/source/blender/blenkernel/BKE_displist.h
+++ b/source/blender/blenkernel/BKE_displist.h
@@ -69,7 +69,8 @@ typedef struct DispList {
 	struct DispList *next, *prev;
 	short type, flag;
 	int parts, nr;
-	short col, rt;              /* rt used by initrenderNurbs */
+	short col;
+	short rt; /* CU_SMOOTH: smooth normals */
 	float *verts, *nors;
 	int *index;
 	int charidx;
diff --git a/source/blender/blenkernel/intern/curve.cpp b/source/blender/blenkernel/intern/curve.cpp
index 7c6d559..57bece1 100644
--- a/source/blender/blenkernel/intern/curve.cpp
+++ b/source/blender/blenkernel/intern/curve.cpp
@@ -150,7 +150,7 @@ void BKE_nurb_knot_calc_u(Nurb *nu)
 {
 	int pnts=nu->pntsu, order=nu->orderu;
 	float *knots = (float*)MEM_mallocN(sizeof(float)*(pnts+2*order), "NURB_knots_u");
-	BKE_nurb_knot_calc(nu->flagu, pnts, order, knots);
+	BKE_bspline_knot_calc(nu->flagu, pnts, order, knots);
 	if (nu->knotsu) MEM_freeN(nu->knotsu);
 	nu->knotsu = knots;
 }
@@ -159,7 +159,7 @@ void BKE_nurb_knot_calc_v(Nurb *nu)
 {
 	int pnts=nu->pntsv, order=nu->orderv;
 	float *knots = (float*)MEM_mallocN(sizeof(float)*(pnts+2*order), "NURB_knots_v");
-	BKE_nurb_knot_calc(nu->flagv, pnts, order, knots);
+	BKE_bspline_knot_calc(nu->flagv, pnts, order, knots);
 	if (nu->knotsv) MEM_freeN(nu->knotsv);
 	nu->knotsv = knots;
 }
@@ -4006,7 +4006,7 @@ void BKE_nurb_make_displist(struct Nurb *nu, struct DispList *dl) {
 	// Trim the uniform grid in 2D UV space
 	GridMesh *gm = new GridMesh();
 	int coords_len = (totu+1)*(totv+1)*2;
-	GridMeshCoord *coords = NULL;
+	GridMeshCoord *coords=NULL, *nors=NULL;
 	if (!remap_coords) {
 		coords = (GridMeshCoord*)MEM_mallocN(coords_len * sizeof(GridMeshCoord), "NURBS_tess_1");
 		gm->mallocN = MEM_mallocN;
@@ -4101,6 +4101,7 @@ void BKE_nurb_make_displist(struct Nurb *nu, struct DispList *dl) {
 	if (remap_coords) {
 		int num_used_idxs = int(used_idxs->size());
 		coords = (GridMeshCoord*)MEM_mallocN(3*sizeof(float)*num_used_idxs, "NURBS_tess_2.3");
+		nors = (GridMeshCoord*)MEM_mallocN(3*sizeof(float)*num_used_idxs, "NURBS_tess_2.4");
 		coords_len = num_used_idxs;
 		int newidx=0;
 		std::map<int,int>::iterator it=used_idxs->begin(),end=used_idxs->end();
@@ -4116,56 +4117,26 @@ void BKE_nurb_make_displist(struct Nurb *nu, struct DispList *dl) {
 	}
 	dl->verts = (float*)coords;
 	dl->index = idxs;
-	dl->nors = NULL;
+	dl->nors = (float*)nors;
 	dl->type = DL_INDEX3;
 	dl->parts = ii/3;
 	dl->nr = coords_len;
+	if (nu->flag&CU_SMOOTH)
+		dl->rt |= CU_SMOOTH;
 	
 	// Pushforward through the NURBS map
-	float basisu[2][NURBS_MAX_ORDER], basisv[2][NURBS_MAX_ORDER];
-	memset(basisu, 0xFF, sizeof(basisu));
-	memset(basisv, 0xFF, sizeof(basisv));
-	int iu, iv;
-	int orderu=nu->orderu, orderv=nu->orderv, pntsu=nu->pntsu, pntsv=nu->pntsv;
-	int coord=0;
-	float cached_v=0.0/0.0;
-	for (; coord<coords_len; coord++) {
+	BSplineCacheU cacheU;
+	cacheU.u = 1.0/0; // First eval should always miss
+	for (int coord=0; coord<coords_len; coord++) {
 		float *xyz = (float*)&coords[coord];
-		// Right now xyz = {u,v,0.0}. Apply the NURBS map to transform it to {x,y,z}
-		if (xyz[1]!=cached_v) {
-			/* only N(i-p)p, N(i-p+1)p, ..., Nip are nz*/
-			iv = BKE_bspline_nz_basis_range(xyz[1], nu->knotsv, nu->pntsv, orderv);
-			BKE_bspline_basis_eval(xyz[1], iv, nu->knotsv, nu->pntsv, orderv, 1, basisv);
-			if (xyz[0]>0.75) {
-				printf("vcoeff(%f): ",xyz[1]);
-				for (int l=0; l<orderv; l++)
-					printf((l!=orderv-1)?"%f, ":"%f\n",basisv[0][l]);
-			}
-			cached_v = xyz[1];
-		}
-		iu = BKE_bspline_nz_basis_range(xyz[0], nu->knotsu, nu->pntsu, orderu);
-		BKE_bspline_basis_eval(xyz[0], iu, nu->knotsu, nu->pntsu, orderu, 1, basisu);
-		if (xyz[0]>0.75) {
-			printf("ucoeff(%f): ",xyz[0]);
-			for (int l=0; l<orderu; l++)
-				printf((l!=orderu-1)?"%f, ":"%f\n",basisu[0][l]);
-		}
-		cached_v = xyz[1];
-		float accum[3] = {0,0,0};
-		float hom_denominator = 0;
-		for (int vi=0; vi<orderv; vi++) {
-			for (int ui=0; ui<orderu; ui++) {
-				float Nu=basisu[0][ui], Nv=basisv[0][vi];
-				int ptu = iu-(orderu-1)+ui;
-				int ptv = iv-(orderv-1)+vi;
-				BPoint& ctrlpt = nu->bp[ptu+pntsu*ptv];
-				float hom_wt = Nu*Nv*ctrlpt.vec[3];
-				hom_denominator += hom_wt;
-				float wcp[3]; mul_v3_v3fl(wcp, ctrlpt.vec, hom_wt);
-				add_v3_v3(accum, wcp);
-			}
-		}
-		mul_v3_v3fl(xyz, accum, 1/hom_denominator);
+		float *norm = (float*)&nors[coord];
+		BPoint out[3]; // { surf_pt, u_partial_deriv, v_partal_deriv }
+		BKE_nurbs_surf_eval(xyz[0], xyz[1],
+							nu->pntsu, nu->orderu, nu->knotsu,
+							nu->pntsv, nu->orderv, nu->knotsv,
+							nu->bp, 1, out, &cacheU);
+		copy_v3_v3(xyz, out[0].vec);
+		cross_v3_v3v3(norm, out[1].vec, out[2].vec);
 	}
 	
 	// Cleanup
diff --git a/source/blender/blenkernel/intern/curve_eval.cpp b/source/blender/blenkernel/intern/curve_eval.cpp
index cbd2396..781974a 100644
--- a/source/blender/blenkernel/intern/curve_eval.cpp
+++ b/source/blender/blenkernel/intern/curve_eval.cpp
@@ -38,6 +38,7 @@
 extern "C" {
 #include "BKE_curve.h"
 #include "DNA_curve_types.h"
+#include "BLI_math.h"
 }
 #endif
 
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 55b8ae5..9d741ec 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -1262,7 +1262,6 @@ void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase,
 	uint64_t timer_stop = mach_absolute_time();
 	int t = timer_stop-timer_start;
 	nu = nubase.first;
-	printf("%i %i %i %i\n",len,nu->pntsu*nu->resolu,nu->pntsv*nu->resolv,t);
 	BKE_nurbList_free(&nubase);
 }
 
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index a0f6d0d..400e934 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -4244,6 +4244,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
 				}
 				else
 					glNormal3fv(ndata);
+				if (dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH);
 
 				glDrawElements(GL_TRIANGLES, 3 * dl->parts, GL_UNSIGNED_INT, dl->index);
 
diff --git a/tests/interactive/curve_eval.h b/tests/interactive/curve_eval.h
index 8dbe657..d48f347 100644
--- a/tests/interactive/curve_eval.h
+++ b/tests/interactive/curve_eval.h
@@ -41,7 +41,7 @@ typedef struct BPoint {
  * so that a surface patch only has to evaluate once per row. We could do
  * this with columns, too, but at a much worse space/time tradeoff.
  */
-typedef struct BSplineCache {
+typedef struct BSplineCacheU {
 	float u;
 	int iu;
 	float Nu[NURBS_MAX_ORDER][NURBS_MAX_ORDER];
@@ -58,6 +58,10 @@ extern "C" {
 							   int pntsv, int orderv, float *V,
 							   BPoint *P, int nd, BPoint *out,
 							   bool premultiply_weights=false, BSplineCacheU *ucache=NULL);
+	void BKE_nurbs_surf_eval(float u, float v,
+							 int pntsu, int orderu, float *U,
+							 int pntsv, int orderv, float *V,
+							 BPoint *P, int nd, BPoint *out, BSplineCacheU *ucache=NULL);
 }
 
 inline void madd_v4_v4fl(float r[4], const float a[4], float f)
diff --git a/tests/interactive/nurbs_derivative_eval.cpp b/te

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list