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

java - Andrioid studio start fail: Fatal error initializing 'null' -

android - Gradle sync Error:Configuration with name 'default' not found -

StringGrid issue in Delphi XE8 firemonkey mobile app -