ios - SceneKit - Draw 3D Parabola -


i'm given 3 points , need draw smooth 3d parabola. trouble curved line choppy , has weird divots in it

parabola

here code...

func drawjump(jump: jump){     let halfdistance = jump.distance.floatvalue/2 float     let tup = calcparabolavalues(0.0, y1: 0.0, x2: halfdistance, y2: jump.height.floatvalue, x3: jump.distance.floatvalue, y3: 0)     println("tuple \tup")      var currentx = 0 float     var increment = jump.distance.floatvalue / float(50)     while currentx < jump.distance.floatvalue - increment {          let x1 = float(currentx)         let x2 = float((currentx+increment))         let y1 = calcparabolayval(tup.a, b: tup.b, c: tup.c, x: x1)         let y2 = calcparabolayval(tup.a, b: tup.b, c: tup.c, x: x2)          drawline(x1, y1: y1, x2: x2, y2: y2)          currentx += increment     } }  func calcparabolavalues(x1: float, y1: float, x2: float, y2: float, x3: float, y3: float) -> (a: float, b: float, c: float) {     println(x1, y1, x2, y2, x3, y3)     let = y1/((x1-x2)*(x1-x3)) + y2/((x2-x1)*(x2-x3)) + y3/((x3-x1)*(x3-x2))     let b = (-y1*(x2+x3)/((x1-x2)*(x1-x3))-y2*(x1+x3)/((x2-x1)*(x2-x3))-y3*(x1+x2)/((x3-x1)*(x3-x2)))     let c = (y1*x2*x3/((x1-x2)*(x1-x3))+y2*x1*x3/((x2-x1)*(x2-x3))+y3*x1*x2/((x3-x1)*(x3-x2)))      return (a, b, c) }  func calcparabolayval(a:float, b:float, c:float, x:float)->float{     return * x * x + b * x + c }  func drawline(x1: float, y1: float,x2: float, y2: float) {     println("drawline \(x1) \(y1) \(x2) \(y2)")     let positions: [float32] = [         x1, y1, 0,         x2, y2, 0     ]     let positiondata = nsdata(bytes: positions, length: sizeof(float32)*positions.count)     let indices: [int32] = [0, 1]     let indexdata = nsdata(bytes: indices, length: sizeof(int32) * indices.count)      let source = scngeometrysource(data: positiondata, semantic: scngeometrysourcesemanticvertex, vectorcount: indices.count, floatcomponents: true, componentspervector: 3, bytespercomponent: sizeof(float32), dataoffset: 0, datastride: sizeof(float32) * 3)     let element = scngeometryelement(data: indexdata, primitivetype: scngeometryprimitivetype.line, primitivecount: indices.count, bytesperindex: sizeof(int32))      let line = scngeometry(sources: [source], elements: [element])     self.rootnode.addchildnode( scnnode(geometry: line)) }  func renderer(arenderer: scnscenerenderer, willrenderscene scene: scnscene, attime time: nstimeinterval) {     gllinewidth(20) } 

i have figure out how animate arc left right. can me out? swift or objective c fine. appreciated. thanks!

i'd recommend using scnshape create parabola. start, you'll need represent parabola bézier curve. can use uibezierpath that. animation, find shader modifiers nice fit cases this.

the parabola

watch out, though — want path represents open stroke of arc. if this:

let path = uibezierpath() path.movetopoint(cgpointzero) path.addquadcurvetopoint(cgpoint(x: 100, y: 0), controlpoint: cgpoint(x: 50, y: 200)) 

you'll filled-in parabola, (seen in 2d in debugger quick look, extruded in 3d scnshape):

filled parabolafilled parabola in 3d

to create closed shape that's arc, you'll need trace on curve, little bit away original:

let path = uibezierpath() path.movetopoint(cgpointzero) path.addquadcurvetopoint(cgpoint(x: 100, y: 0), controlpoint: cgpoint(x: 50, y: 200)) path.addlinetopoint(cgpoint(x: 99, y: 0)) path.addquadcurvetopoint(cgpoint(x: 1, y: 0), controlpoint: cgpoint(x: 50, y: 198)) 

open parabolaopen parabola in 3d

that's better.

... in three-dee!

how make 3d? make scnshape extrusion depth like:

let shape = scnshape(path: path, extrusiondepth: 10) 

and set in scene:

shape.firstmaterial?.diffuse.contents = skcolor.bluecolor() let shapenode = scnnode(geometry: shape) shapenode.pivot = scnmatrix4maketranslation(50, 0, 0) shapenode.eulerangles.y = float(-m_pi_4) root.addchildnode(shapenode) 

here i'm using pivot make shape rotate around major axis of parabola, instead of y = 0 axis of planar bézier curve. , making blue. also, root shortcut made view's scene's root node.

animating

the shape of parabola doesn't need change through animation — need visual effect progressively reveals along x-axis. shader modifiers great fit that, because can make animated effect per-pixel instead of per-vertex , expensive work on gpu.

here's shader snippet uses progress parameter, varying 0 1, set opacity based on x-position:

// declare variable can set scenekit code uniform float progress; // tell scenekit shader uses transparency correct draw order #pragma transparent // position in model space vec4 mpos = u_inversemodelviewtransform * vec4(_surface.position, 1.0); // bit of math ramp alpha based on progress-adjusted position _surface.transparent.a = clamp(1.0 - ((mpos.x + 50.0) - progress * 200.0) / 50.0, 0.0, 1.0); 

set shader modifier surface entry point, , can animate progress variable:

let modifier = "uniform float progress;\n #pragma transparent\n vec4 mpos = u_inversemodelviewtransform * vec4(_surface.position, 1.0);\n _surface.transparent.a = clamp(1.0 - ((mpos.x + 50.0) - progress * 200.0) / 50.0, 0.0, 1.0);" shape.shadermodifiers = [ scnshadermodifierentrypointsurface: modifier ] shape.setvalue(0.0, forkey: "progress")  scntransaction.begin() scntransaction.setanimationduration(10) shape.setvalue(1.0, forkey: "progress") scntransaction.commit() 

animating parabola

further considerations

here's whole thing in form can paste (ios) playground. few things left exercises reader, plus other notes:

  • factor out magic numbers , make function or class can alter size/shape of parabola. (remember can scale scenekit nodes relative other scene elements, don't have use same units.)

  • position parabola relative other scene elements. if take away line sets pivot, shapenode.position left end of parabola. change parabola's length (or scale it), rotate around y-axis, , can make other end line other node. (for fire ze missiles at?)

  • i threw swift 2 beta, don't think there's swift-2-specific syntax in there — porting 1.2 if need deploy should straightforward.

  • if want on os x, it's bit trickier — there, scnshape uses nsbezierpath, unlike uibezierpath doesn't support quadratic curves. easy way out fake elliptical arc.


Comments

Popular posts from this blog

how to do line continuation in perl debugger for entering raw multi-line text (EOT)? -

javascript - Create websocket without connecting -

android - Linear layout children not scrolling -