Пример #1
0
static Point3f NURBSEvaluateSurface(int uOrder, const Float *uKnot, int ucp,
                                    Float u, int vOrder, const Float *vKnot,
                                    int vcp, Float v, const Homogeneous3 *cp,
                                    Vector3f *dpdu, Vector3f *dpdv) {
    Homogeneous3 *iso = ALLOCA(Homogeneous3, std::max(uOrder, vOrder));

    int uOffset = KnotOffset(uKnot, uOrder, ucp, u);
    int uFirstCp = uOffset - uOrder + 1;
    Assert(uFirstCp >= 0 && uFirstCp + uOrder - 1 < ucp);

    for (int i = 0; i < uOrder; ++i)
        iso[i] = NURBSEvaluate(vOrder, vKnot, &cp[uFirstCp + i], vcp, ucp, v);

    int vOffset = KnotOffset(vKnot, vOrder, vcp, v);
    int vFirstCp = vOffset - vOrder + 1;
    Assert(vFirstCp >= 0 && vFirstCp + vOrder - 1 < vcp);

    Homogeneous3 P =
        NURBSEvaluate(uOrder, uKnot, iso - uFirstCp, ucp, 1, u, dpdu);

    if (dpdv) {
        for (int i = 0; i < vOrder; ++i)
            iso[i] = NURBSEvaluate(uOrder, uKnot, &cp[(vFirstCp + i) * ucp],
                                   ucp, 1, u);
        (void)NURBSEvaluate(vOrder, vKnot, iso - vFirstCp, vcp, 1, v, dpdv);
    }
    return Point3f(P.x / P.w, P.y / P.w, P.z / P.w);
}
Пример #2
0
static Point
NURBSEvaluateSurface(int uOrder, const float *uKnot, int ucp, float u,
		     int vOrder, const float *vKnot, int vcp, float v,
		     const Homogeneous3 *cp, Vector *dPdu, Vector *dPdv) {
    Homogeneous3 *iso = (Homogeneous3 *)alloca(max(uOrder, vOrder) *
					       sizeof(Homogeneous3));

    int uOffset = KnotOffset(uKnot, uOrder, ucp, u);
    int uFirstCp = uOffset - uOrder + 1;
    assert(uFirstCp >= 0 && uFirstCp + uOrder - 1 < ucp);

    for (int i = 0; i < uOrder; ++i)
		iso[i] = NURBSEvaluate(vOrder, vKnot, &cp[uFirstCp + i], vcp,
			       ucp, v);

    int vOffset = KnotOffset(vKnot, vOrder, vcp, v);
    int vFirstCp = vOffset - vOrder + 1;
    assert(vFirstCp >= 0 && vFirstCp + vOrder - 1 < vcp);

    Homogeneous3 P = NURBSEvaluate(uOrder, uKnot, iso - uFirstCp, ucp,
				   1, u, dPdu);

    if (dPdv) {
		for (int i = 0; i < vOrder; ++i)
		    iso[i] = NURBSEvaluate(uOrder, uKnot, &cp[(vFirstCp+i)*ucp], ucp,
				   1, u);
		(void)NURBSEvaluate(vOrder, vKnot, iso - vFirstCp, vcp, 1, v, dPdv);
    }
    return Point(P.x/P.w, P.y/P.w, P.z/P.w);;
}
Пример #3
0
static Homogeneous3
NURBSEvaluate(int order, const float *knot, const Homogeneous3 *cp, int np,
	      int cpStride, float t, Vector *deriv = NULL) {
//    int nKnots = np + order;
    float alpha;

    int knotOffset = KnotOffset(knot, order, np, t);
    knot += knotOffset;

    int cpOffset = knotOffset - order + 1;
    assert(cpOffset >= 0 && cpOffset < np);

    Homogeneous3 *cpWork =
	(Homogeneous3 *)alloca(order * sizeof(Homogeneous3));
    for (int i = 0; i < order; ++i)
	cpWork[i] = cp[(cpOffset+i) * cpStride];

    for (int i = 0; i < order - 2; ++i)
	for (int j = 0; j < order - 1 - i; ++j) {
	    alpha = (knot[1 + j] - t) /
		(knot[1 + j] - knot[j + 2 - order + i]);
	    assert(alpha >= 0. && alpha <= 1.);

	    cpWork[j].x = cpWork[j].x * alpha + cpWork[j+1].x * (1 - alpha);
	    cpWork[j].y = cpWork[j].y * alpha + cpWork[j+1].y * (1 - alpha);
	    cpWork[j].z = cpWork[j].z * alpha + cpWork[j+1].z * (1 - alpha);
	    cpWork[j].w = cpWork[j].w * alpha + cpWork[j+1].w * (1 - alpha);
	}

    alpha = (knot[1] - t) / (knot[1] - knot[0]);
    assert(alpha >= 0. && alpha <= 1.);

    Homogeneous3 val(cpWork[0].x * alpha + cpWork[1].x * (1 - alpha),
		     cpWork[0].y * alpha + cpWork[1].y * (1 - alpha),
		     cpWork[0].z * alpha + cpWork[1].z * (1 - alpha),
		     cpWork[0].w * alpha + cpWork[1].w * (1 - alpha));

    if (deriv) {
		float factor = (order - 1) / (knot[1] - knot[0]);
		Homogeneous3 delta((cpWork[1].x - cpWork[0].x) * factor,
			   (cpWork[1].y - cpWork[0].y) * factor,
			   (cpWork[1].z - cpWork[0].z) * factor,
			   (cpWork[1].w - cpWork[0].w) * factor);

		deriv->x = delta.x / val.w - (val.x * delta.w / (val.w * val.w));
		deriv->y = delta.y / val.w - (val.y * delta.w / (val.w * val.w));
		deriv->z = delta.z / val.w - (val.z * delta.w / (val.w * val.w));
    }

    return val;
}