# #StackBounty: #javascript #three.js #3d #nurbs #cubic-bezier How can I create a 3D cubic-bezier curved triangle from 3D points in Three…

### Bounty: 50

Following this topic, I am trying to generate a 3D curved triangle as a NURBS surface, but I don’t understand how to set up my 3D points to do that.

Here is the current implementation :

``````var edges = this.getEdges(), // An edge is a line following 4 dots as a bezier curve.
dots = self.getDotsFromEdges(edges), // Get all dots in order for building the surface.

ctrlPoints = [ // Is generated only once before, but copy-pasted here for this sample code.
[
new THREE.Vector4(0, 0, 0, 1),
new THREE.Vector4(0, 0, 0, 1),
new THREE.Vector4(0, 0, 0, 1),
new THREE.Vector4(0, 0, 0, 1)
],
[
new THREE.Vector4(0, 0, 0, 1),
new THREE.Vector4(0, 0, 0, 1),
new THREE.Vector4(0, 0, 0, 1),
new THREE.Vector4(0, 0, 0, 1)
],
[
new THREE.Vector4(0, 0, 0, 1),
new THREE.Vector4(0, 0, 0, 1),
new THREE.Vector4(0, 0, 0, 1),
new THREE.Vector4(0, 0, 0, 1)
]
],

nc,
deg1 = ctrlPoints.length - 1,
knots1 = [],
deg2 = 3,                           // Cubic bezier
knots2 = [0, 0, 0, 0, 1, 1, 1, 1],  // <-
cpts,
nurbs ;

nc = ctrlPoints.length ;
while (nc-- > 0) knots1.push(0) ;
nc = ctrlPoints.length ;
while (nc-- > 0) knots1.push(1) ;

// The following seems to be the problem... :

cpts = ctrlPoints[0] ;
cpts[0].set(dots[0].x, dots[0].y, dots[0].z, 1) ;
cpts[1].set(dots[1].x, dots[1].y, dots[1].z, 1) ;
cpts[2].set(dots[2].x, dots[2].y, dots[2].z, 1) ;
cpts[3].set(dots[3].x, dots[3].y, dots[3].z, 1) ;

cpts = ctrlPoints[1] ;
cpts[0].set(dots[6].x, dots[6].y, dots[6].z, 1) ;
cpts[1].set(dots[5].x, dots[5].y, dots[5].z, 1) ;
cpts[2].set(dots[4].x, dots[4].y, dots[4].z, 1) ;
cpts[3].set(dots[3].x, dots[3].y, dots[3].z, 1) ;

cpts = ctrlPoints[2] ;
cpts[0].set(dots[6].x, dots[6].y, dots[6].z, 1) ;
cpts[1].set(dots[7].x, dots[7].y, dots[7].z, 1) ;
cpts[2].set(dots[8].x, dots[8].y, dots[8].z, 1) ;
cpts[3].set(dots[0].x, dots[0].y, dots[0].z, 1) ;

nurbs = new THREE.NURBSSurface(deg1, deg2, knots1, knots2, ctrlPoints) ;

this.mesh.geometry.dispose() ;
this.mesh.geometry = new THREE.ParametricBufferGeometry(function(u, v, target) {
return nurbs.getPoint(u, v, target) ;
}, 10, 10) ;
``````

And here is the result:

I tried many different settings but can’t find any working well.

Note: The white points are the edges ends ; The red points are the bezier curve middle points.
Note 2: `dots[0]` refers to the point `0` in the sample picture, and so on.

Here is working snippet (and fiddle version here)

``````const
PI = Math.PI,
sin = Math.sin,
cos = Math.cos,
W = 480,
H = 400,
log = console.log,
DISTANCE = 100 ;

let renderer = new THREE.WebGLRenderer({
canvas : document.querySelector('canvas'),
antialias : true,
alpha : true
}),
camera = new THREE.PerspectiveCamera(25, W/H),
scene = new THREE.Scene(),
center = new THREE.Vector3(0, 0, 0),

pts = [] ;

renderer.setClearColor(0x000000, 0) ;

renderer.setSize(W, H) ;
// camera.position.set(-48, 32, 80) ;
camera.position.set(0, 0, DISTANCE) ;
camera.lookAt(center) ;

function createPoint(x, y, z, color) {
let pt = new THREE.Mesh(
new THREE.SphereGeometry(1, 10, 10),
new THREE.MeshBasicMaterial({ color })
) ;
pt.position.set(x, y, z) ;
pt.x = x ;
pt.y = y ;
pt.z = z ;
pts.push(pt) ;

}

function createEdge(pt1, pt2, pt3, pt4) {
let curve = new THREE.CubicBezierCurve3(
pt1.position,
pt2.position,
pt3.position,
pt4.position
),
mesh = new THREE.Mesh(
new THREE.TubeGeometry(curve, 8, 0.5, 8, false),
new THREE.MeshBasicMaterial({
color : 0x203040
})
) ;

}

///////////////////////////////////////////////

// POINTS //
createPoint(-16, -8, 0, 0xcc0000) ; // RED
createPoint(-8, -12, 0, 0x999999) ;
createPoint(8, -12, 0, 0x888888) ;
createPoint(16, -8, 0, 0x00cc00) ; // GREEN
createPoint(12, -6, -8, 0x777777) ;
createPoint(8, 6, -8, 0x666666) ;
createPoint(0, 12, 0, 0x0000cc) ; // BLUE
createPoint(-8, 6, -8, 0x555555) ;
createPoint(-12, -6, -8, 0x444444) ;

// EDGES //
createEdge(pts[0], pts[1], pts[2], pts[3]) ;
createEdge(pts[3], pts[4], pts[5], pts[6]) ;
createEdge(pts[6], pts[7], pts[8], pts[0]) ;

// SURFACE //
let ctrlPoints = [
[
new THREE.Vector4(pts[0].x, pts[0].y, pts[0].z, 1),
new THREE.Vector4(pts[1].x, pts[1].y, pts[1].z, 1),
new THREE.Vector4(pts[2].x, pts[2].y, pts[2].z, 1),
new THREE.Vector4(pts[3].x, pts[3].y, pts[3].z, 1)
],
[
new THREE.Vector4(pts[6].x, pts[6].y, pts[6].z, 1),
new THREE.Vector4(pts[5].x, pts[5].y, pts[5].z, 1),
new THREE.Vector4(pts[4].x, pts[4].y, pts[4].z, 1),
new THREE.Vector4(pts[3].x, pts[3].y, pts[3].z, 1)
],
[
new THREE.Vector4(pts[6].x, pts[6].y, pts[6].z, 1),
new THREE.Vector4(pts[7].x, pts[7].y, pts[7].z, 1),
new THREE.Vector4(pts[8].x, pts[8].y, pts[8].z, 1),
new THREE.Vector4(pts[0].x, pts[0].y, pts[0].z, 1)
]
],

nc,
deg1 = ctrlPoints.length - 1,
knots1 = [],
deg2 = 3,                           // Cubic bezier
knots2 = [0, 0, 0, 0, 1, 1, 1, 1],  // <-
cpts,
nurbs ;

nc = ctrlPoints.length ;
while (nc-- > 0) knots1.push(0) ;
nc = ctrlPoints.length ;
while (nc-- > 0) knots1.push(1) ;

nurbs = new THREE.NURBSSurface(deg1, deg2, knots1, knots2, ctrlPoints) ;

let surfaceMesh = new THREE.Mesh(
new THREE.ParametricBufferGeometry(function(u, v, target) {
return nurbs.getPoint(u, v, target) ;
}, 10, 10),
new THREE.MeshBasicMaterial({
side : THREE.DoubleSide,
opacity : 0.9,
transparent : true,
color : 0x405060
})
) ;

///////////////////////////////////////////////

let azimut = 0,
pitch = 90,
isDown = false,
prevEv ;

function down(de) {
prevEv = de ;
isDown = true ;
}

function move(me) {
if (!isDown) return ;

azimut -= (me.clientX - prevEv.clientX) * 0.5 ;
azimut %= 360 ;
if (azimut < 0) azimut = 360 - azimut ;

pitch -= (me.clientY - prevEv.clientY) * 0.5 ;
if (pitch < 1) pitch = 1 ;
if (pitch > 180) pitch = 180 ;

prevEv = me ;

let theta = pitch / 180 * PI,
phi = azimut / 180 * PI,

camera.position.set(
) ;
camera.lookAt(center) ;

renderer.render(scene, camera) ;
}

function up(ue) {
isDown = false ;
}

renderer.domElement.onmousedown = down ;
window.onmousemove = move ;
window.onmouseup = up ;

renderer.render(scene, camera) ;``````
``````body {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background: #1c2228;
overflow: hidden;
}``````
``````https://cdnjs.cloudflare.com/ajax/libs/three.js/101/three.min.js
https://threejs.org/examples/js/curves/NURBSUtils.js
https://threejs.org/examples/js/curves/NURBSCurve.js
https://threejs.org/examples/js/curves/NURBSSurface.js

<canvas></canvas>``````

Get this bounty!!!

This site uses Akismet to reduce spam. Learn how your comment data is processed.