2014-11-23 40 views
0

我正在尋找通過在Android上圍繞Y軸旋轉樣條曲線來創建3D對象的方法。結果應該是一個碗/玻璃狀物:哪個框架用於從樣條曲線中拉伸3D對象

http://www.3d-resources.com/cinema_4d_tutorials/realistic_glass_tutorial.html

形式的形狀應該是動態的,用戶應該能夠tweek樣條曲線的半徑和控制點中的應用程序。

基本上我正在尋找最直接的方式來實現這一點。有人能指引我朝着正確的方向嗎? (框架,示範實施......)

這種建模技術有沒有一個衆所周知的名字? (在CINEMA 4D它被稱爲「車牀NURBS」)

----- ----- EDIT

我的輸入是二維控制點(貝塞爾路徑)和旋轉之間的半徑的序列軸和樣條曲線。 我的輸出應該是通過圍繞軸旋轉樣條曲線創建的對象的實時3D渲染。

+0

這個問題是非常廣闊的。你的投入是什麼?你的預期產出是什麼? – 2014-11-23 21:15:30

+0

編輯我的問題。 – stoefln 2014-11-23 21:18:51

+0

好,所以你實際上需要兩個不同的功能:一個函數執行繞一個軸的樣條曲線的旋轉,另一個函數執行所述對象的渲染。這是一個非常廣泛的要求。到目前爲止你做了什麼? – 2014-11-23 23:40:18

回答

1

關於buzier curve和約surface rotation的信息。

您可以從github獲取代碼。
我幾年前寫過這篇文章,當時我是Java新手,所以代碼質量可能有點差。

輸出: enter image description here

主要的類:

貝茲曲線:

package kpi.ua.shapes; 

import java.awt.Graphics2D; 
import java.util.LinkedList; 
import java.util.List; 

public class BezierCurve { 

    private List<Point> allPoints; 

    public BezierCurve(List<Point> allPoints) { 
     this.allPoints = allPoints; 
    } 

    public Point getValue(double t) { 
     Point result = new Point(); 
     int i = 0; 
     Double x=new Double(0); 
     Double y=new Double(0); 
     for (Point p : allPoints) { 
      x+=p.getX() * b(i, allPoints.size()-1, t); 
      y+=p.getY() * b(i, allPoints.size()-1, t); 
      i++; 
     } 
     result.setX(x); 
     result.setY(y); 
     return result; 
    } 

    private Double b(int i, int n, double t) { 
     return fact(n)* Math.pow(t, i) * Math.pow(1 - t, n - i)/(fact(i) * fact(n - i)); 
    } 

    private int fact(int num) { 
     return (num == 0) ? 1 : num * fact(num - 1); 
    } 

    public void drawCarcass(Graphics2D gr) { 
     Double[] x=new Double[allPoints.size()]; 
     Double[] y=new Double[allPoints.size()]; 
     int i=0; 
     for(Point p:allPoints){ 
      x[i]=p.getX(); 
      y[i]=p.getY(); 
      i++; 
     } 
     // gr.drawPolygon(x, y, i); 
    } 

    public List<Line> getCurve(){ 
     LinkedList<Line> curve=new LinkedList<Line>(); 
     Double t=0.0; 
     Point prev = getValue(t); 
     Point next; 
     while (t <= 1) { 
      next =getValue(t); 
      curve.add(new Line(prev,next)); 
      // gr.drawLine(prev.getX(), prev.getY(), next.getX(), next.getY()); 
      prev = next; 
      t += 0.001; 
     } 
     next = getValue(t); 
     curve.add(new Line(prev,next)); 
     return curve; 
     //gr.drawLine(prev.getX(), prev.getY(), next.getX(), next.getY()); 
    } 
    public void drawCurve(Graphics2D gr){ 
//  Double t=0.0; 
//  Point prev = getValue(t); 
//  Point next; 
//  gr.setColor(Color.yellow); 
//  gr.setStroke(new BasicStroke(2.5f)); 
//  while (t <= 1) { 
//   next =getValue(t);   
//   // gr.drawLine(prev.getX(), prev.getY(), next.getX(), next.getY()); 
//   prev = next; 
//   t += 0.001; 
//  } 
//  next = getValue(t); 
     // gr.drawLine(prev.getX(), prev.getY(), next.getX(), next.getY());   
    } 


} 

複合物:

package kpi.ua.shapes; 

public class Complex extends Point { 

    private Double re; 
    private Double im; 

    public Complex(Double im, Double re) { 
     this.im = im; 
     this.re = re; 
     Double r = Math.sqrt(im * im + re * re); 
     Double fi = Math.atan(im/re); 
     this.x=r * Math.cos(fi); 
     this.y=r * Math.sin(fi); 
    } 

    public Double getRe() { 
     return re; 
    } 

    public void setRe(Double re) { 
     this.re = re; 
    } 

    public Double getIm() { 
     return im; 
    } 

    public void setIm(Double im) { 
     this.im = im; 
    } 

} 

錐形:

package kpi.ua.shapes; 

public class Cone { 
    private Double a; 
    private Double b; 
    private Double c; 
    private Double fi; 

    public Cone() { 
     super(); 
    } 
    public Cone(Double a, Double b, Double c) { 
     super(); 
     this.a = a; 
     this.b = b; 
     this.c = c; 
    } 
    public Double getA() { 
     return a; 
    } 
    public void setA(Double a) { 
     this.a = a; 
    } 
    public Double getB() { 
     return b; 
    } 
    public void setB(Double b) { 
     this.b = b; 
    } 
    public Double getC() { 
     return c; 
    } 
    public void setC(Double c) { 
     this.c = c; 
    } 
    public Double getFi() { 
     return fi; 
    } 
    public void setFi(Double fi) { 
     this.fi = fi; 
    } 
    public Point3D getPoint(Double fi,Double r){ 
     Double x=this.a*r*Math.cos(fi); 
     Double y=this.b*r*Math.sin(fi); 
     Double z=this.c*r; 
     return new Point3D(x, y, z); 
    } 
} 

ConeSurface:

package kpi.ua.shapes; 

import java.awt.Graphics2D; 
import java.util.LinkedList; 
import java.util.List; 

import kpi.ua.util.ControlUtil; 
import kpi.ua.util.GraphicUtil; 

public class ConeSurface { 
    private List<Point3D> conePoints; 
    public List<Point3D> getConePoints() { 
     return conePoints; 
    } 
    public void setConePoints(List<Point3D> conePoints) { 
     this.conePoints = conePoints; 
    } 

    public void calcConePoints(){ 
     Cone cone = new Cone(ControlUtil.CONE_PARAMETR_A, ControlUtil.CONE_PARAMETR_B, ControlUtil.CONE_PARAMETR_C); 
     Double r = ControlUtil.CONE_START_RADIOUS; 
     conePoints=new LinkedList<Point3D>(); 
     while (r >= 0) { 
      for (double fi = 0; fi < 2 * Math.PI; fi += ControlUtil.STEP_BY_FI) { 
       conePoints.add(cone.getPoint(fi, r)); 
       conePoints.add(cone.getPoint(fi+ControlUtil.STEP_BY_FI, r)); 
       if(r!=0){ 
        conePoints.add(cone.getPoint(fi, r-1)); 
       } 
      } 
      r--; 
     } 
    } 
    public void drawCone(Graphics2D gr){ 
     if(conePoints==null) 
      calcConePoints(); 
     GraphicUtil.drawTriangulation(gr, conePoints); 
    } 
} 

線:

package kpi.ua.shapes; 


public class Line { 
    private Point from; 
    private Point to; 
    public Line(Point from, Point to) { 
     super(); 
     this.from = from; 
     this.to = to; 
    } 
    public Point getFrom() { 
     return from; 
    } 
    public void setFrom(Point from) { 
     this.from = from; 
    } 
    public Point getTo() { 
     return to; 
    } 
    public void setTo(Point to) { 
     this.to = to; 
    } 
} 

Line3D:

package kpi.ua.shapes; 

public class Line3D { 
    private Point3D from; 
    private Point3D to; 

    public Line3D() { 
     super(); 
    } 

    public Line3D(Point3D from, Point3D to) { 
     super(); 
     this.from = from; 
     this.to = to; 
    } 

    public Point3D getFrom() { 
     return from; 
    } 

    public void setFrom(Point3D from) { 
     this.from = from; 
    } 

    public Point3D getTo() { 
     return to; 
    } 

    public void setTo(Point3D to) { 
     this.to = to; 
    } 

    public Line get2DVision() { 
     return new Line(from.get2DVision(), to.get2DVision()); 
    } 
} 

點:

package kpi.ua.shapes; 

public class Point { 

    protected Double x; 
    protected Double y; 

    public Point() { 
    } 

    public Point(Double x, Double y) { 
     this.x = x; 
     this.y = y; 
    } 

    public Double getX() { 
     return x; 
    } 

    public void setX(Double x) { 
     this.x = x; 
    } 

    public Double getY() { 
     return y; 
    } 

    public void setY(Double y) { 
     this.y = y; 
    } 
} 

三維點:

package kpi.ua.shapes; 

public class Point3D extends Point { 
    private Double z; 

    public Point3D(Double x, Double y, Double z) { 
     super(x, y); 
     this.z = z; 
    } 

    public Double getZ() { 
     return z; 
    } 

    public void setZ(Double z) { 
     this.z = z; 
    } 

    /**Èçîìåòðèÿ 
    * @return 
    */ 
    public Point get2DVision() { 
     Double cx=(1.0/Math.sqrt(6))*(Math.sqrt(3)*this.x-Math.sqrt(3)*this.z); 
     Double cy=(1.0/Math.sqrt(6))*(Math.sqrt(2)*this.x-Math.sqrt(2)*this.y+Math.sqrt(2)*this.z); 
     return new Point(cx, cy); 
    } 

    @Override 
    public String toString() { 
     return "Point3D [z=" + z + ", x=" + x + ", y=" + y + "]"; 
    } 


} 

SurfaceBasedOnBuzierCurve:

package kpi.ua.shapes; 

import java.awt.Graphics2D; 
import java.util.LinkedList; 
import java.util.List; 

import kpi.ua.util.ControlUtil; 
import kpi.ua.util.GraphicUtil; 

public class SurfaceBasedOnBuzierCurve { 
    private final static Double DEFAULT_STEP_BY_T = 0.05; 
    private final static Double DEFAULT_Q = 1.0; 
    private final static Double DEFAULT_STEP_BY_FI = 0.15; 
    private BezierCurve movingCurve; 
    private List<Point3D> buzierPoints; 

    public SurfaceBasedOnBuzierCurve() { 
     refreshBuzierCurve(); 
    } 

    public List<Point3D> getBuzierPoints() { 
     return buzierPoints; 
    } 

    public void setConePoints(List<Point3D> buzierPoints) { 
     this.buzierPoints = buzierPoints; 
    } 

    public void calcBuzierPoints() { 
     this.buzierPoints = new LinkedList<Point3D>(); 
     Double q = DEFAULT_Q; 
     Point movingPoint; 
     for(double fi=0.0;fi<Math.PI*2;fi+=DEFAULT_STEP_BY_FI){ 
      for(double t=0.0;t<=1.0;t+=DEFAULT_STEP_BY_T){ 
       movingPoint=this.movingCurve.getValue(t); 
       Point3D firstPoint =getSurfacePoint(movingPoint, movingPoint, q, fi); 
       if(t+DEFAULT_STEP_BY_T<=1){ 
        movingPoint=this.movingCurve.getValue(t+DEFAULT_STEP_BY_T); 
        Point3D secondPoint =getSurfacePoint(movingPoint, movingPoint, q, fi); 
        Point3D thirdPoint=getSurfacePoint(movingPoint, movingPoint, q, fi+DEFAULT_STEP_BY_FI); 
        buzierPoints.add(firstPoint); 
        buzierPoints.add(thirdPoint); 
        buzierPoints.add(secondPoint); 

       }    
      } 
     } 
    } 

    /** 
    * Gets 3DPoint on surface via roating line 
    * 
    * @param from 
    * @param to 
    * @param q 
    * @param fi 
    * @return 
    */ 
    public Point3D getSurfacePoint(Point from, Point to, Double q, Double fi) { 
     Double x = from.getX() + (to.getX() - from.getX()) * q; 
     Double y = (from.getY() + (to.getY() - from.getY()) * q) * Math.cos(fi); 
     Double z = (from.getY() + (to.getY() - from.getY()) * q) * Math.sin(fi); 
     return new Point3D(x, y, z); 
    } 

    public void drawBuzierSurface(Graphics2D gr) { 
     if (buzierPoints == null) 
      calcBuzierPoints(); 
     GraphicUtil.drawTriangulation(gr, buzierPoints); 
    } 
    public void refreshBuzierCurve(){ 
     LinkedList<Point> allPoints = new LinkedList<>(); 
     allPoints.add(new Point(ControlUtil.BUZIER_FIRST_X, ControlUtil.BUZIER_FIRST_Y)); 
     allPoints.add(new Point(ControlUtil.BUZIER_SECOND_X, ControlUtil.BUZIER_SECOND_Y)); 
     allPoints.add(new Point(ControlUtil.BUZIER_THIRD_X, ControlUtil.BUZIER_THIRD_Y)); 
     allPoints.add(new Point(ControlUtil.BUZIER_FOURTH_X, ControlUtil.BUZIER_FOURTH_X)); 
     allPoints.add(new Point(ControlUtil.BUZIER_FIFTH_X, ControlUtil.BUZIER_FIFTH_X)); 
     this.movingCurve = new BezierCurve(allPoints); 
    } 
} 

ControlUtil:

package kpi.ua.util; 

import kpi.ua.shapes.Point; 
import kpi.ua.shapes.Point3D; 

public class ControlUtil { 
    public static Double scaleX=1.0; 
    public static Double scaleY=1.0; 
    public static Double scaleZ=1.0; 
    public static long serialVersionUID = 45L; 
    public static Double AXIS_LENGTH = 200.0; 
    public static Point CENTER_AXISES = new Point(300.0, 200.0); 
    public static Point3D AXIS_X; 
    public static Point3D AXIS_Y; 
    public static Point3D AXIS_Z; 
    public static Double CONE_PARAMETR_A=4.0; 
    public static Double CONE_PARAMETR_B=6.0; 
    public static Double CONE_PARAMETR_C=5.0; 
    public static Double CONE_START_RADIOUS=25.0; 
    public static Double STEP_BY_FI=0.2; 
    public static Boolean isDrawCone=false; 


// allPoints.add(new Point(30.0, 10.0)); 
// allPoints.add(new Point(300.0, 210.0)); 
// allPoints.add(new Point(100.0, 200.0)); 
// allPoints.add(new Complex((double) 55.0, (double) 251.0)); 
// allPoints.add(new Complex((double) 155.0, (double) 300.0)); 

    public static Double BUZIER_FIRST_X=30.0; 
    public static Double BUZIER_FIRST_Y=10.0; 

    public static Double BUZIER_SECOND_X=-150.0; 
    public static Double BUZIER_SECOND_Y=110.0; 

    public static Double BUZIER_THIRD_X=100.0; 
    public static Double BUZIER_THIRD_Y=200.0; 

    public static Double BUZIER_FOURTH_X=55.0; 
    public static Double BUZIER_FOURTH_Y=251.0; 

    public static Double BUZIER_FIFTH_X=155.0; 
    public static Double BUZIER_FIFTH_Y=300.0; 


    static{ 
     AXIS_X=new Point3D(AXIS_LENGTH, 0.0 ,0.0); 
     AXIS_Y=new Point3D(0.0,AXIS_LENGTH, 0.0); 
     AXIS_Z=new Point3D(0.0, 0.0, AXIS_LENGTH); 
    } 
} 

GraphicUtil:

package kpi.ua.util; 

import java.awt.Color; 
import java.awt.Graphics2D; 
import java.awt.Polygon; 
import java.util.Iterator; 
import java.util.List; 

import kpi.ua.shapes.Line; 
import kpi.ua.shapes.Line3D; 
import kpi.ua.shapes.Point3D; 

public class GraphicUtil{ 
    public static void drawAxis(Graphics2D gr){ 
     gr.setColor(Color.RED); 
     drawLine(gr,new Line3D(new Point3D(0.0,0.0,0.0),ControlUtil.AXIS_X)); 
     gr.setColor(Color.WHITE); 
     gr.drawString("x", ControlUtil.CENTER_AXISES.getX().intValue()+ControlUtil.AXIS_X.get2DVision().getX().intValue()+5, 
       ControlUtil.CENTER_AXISES.getY().intValue()-ControlUtil.AXIS_X.get2DVision().getY().intValue()); 
     gr.setColor(Color.RED); 
     drawLine(gr,new Line3D(new Point3D(0.0,0.0,0.0),ControlUtil.AXIS_Y)); 
     gr.setColor(Color.WHITE); 
     gr.drawString("y", ControlUtil.CENTER_AXISES.getX().intValue()+ControlUtil.AXIS_Y.get2DVision().getX().intValue()+5, 
       ControlUtil.CENTER_AXISES.getY().intValue()-ControlUtil.AXIS_Y.get2DVision().getY().intValue()); 
     gr.setColor(Color.RED);  
     drawLine(gr,new Line3D(new Point3D(0.0,0.0,0.0),ControlUtil.AXIS_Z)); 
     gr.setColor(Color.WHITE); 
     gr.drawString("z", ControlUtil.CENTER_AXISES.getX().intValue()+ControlUtil.AXIS_Z.get2DVision().getX().intValue()+5, 
       ControlUtil.CENTER_AXISES.getY().intValue()-ControlUtil.AXIS_Z.get2DVision().getY().intValue()); 
    } 
    public static void moveAroundZ(Double fi,List<Point3D> shape){ 
     Double x; 
     Double y; 
     if(shape!=null){ 
      for(Point3D point:shape){ 
       x=point.getX()*Math.cos(fi)+point.getY()*Math.sin(fi); 
       y=point.getX()*Math.sin(fi)-point.getY()*Math.cos(fi); 
       point.setX(x); 
       point.setY(y); 
      } 
     } 
    } 
    public static void moveAroundX(Double fi,List<Point3D> shape){ 
     Double y; 
     Double z; 
     if(shape!=null){ 
      for(Point3D point:shape){ 
       y=-point.getY()*Math.cos(fi)-point.getZ()*Math.sin(fi); 
       z=-point.getY()*Math.sin(fi)+point.getZ()*Math.cos(fi); 
       point.setY(y); 
       point.setZ(z); 
      } 
     } 
    } 
    public static void moveAroundY(Double fi,List<Point3D> shape){ 
     Double x; 
     Double z;  
     if(shape!=null){ 
      for(Point3D point:shape){ 
       x=point.getX()*Math.cos(fi)+point.getZ()*Math.sin(fi); 
       z=-point.getX()*Math.sin(fi)+point.getZ()*Math.cos(fi); 
       point.setX(x); 
       point.setZ(z); 
      } 
     } 
    } 
    public static void drawLine(Graphics2D gr,Line3D line3D){ 
     line3D.getFrom().setX(ControlUtil.scaleX*line3D.getFrom().getX()); 
     line3D.getFrom().setY(ControlUtil.scaleY*line3D.getFrom().getY()); 
     line3D.getFrom().setZ(ControlUtil.scaleZ*line3D.getFrom().getZ()); 
     line3D.getTo().setX(ControlUtil.scaleX*line3D.getTo().getX()); 
     line3D.getTo().setY(ControlUtil.scaleY*line3D.getTo().getY()); 
     line3D.getTo().setZ(ControlUtil.scaleZ*line3D.getTo().getZ()); 
     Line line=line3D.get2DVision(); 
     gr.drawLine((int)Math.round(ControlUtil.CENTER_AXISES.getX()+line.getFrom().getX()), (int)Math.round(ControlUtil.CENTER_AXISES.getY()-line.getFrom().getY()), (int)Math.round(ControlUtil.CENTER_AXISES.getX()+line.getTo().getX()),(int) Math.round(ControlUtil.CENTER_AXISES.getY()-line.getTo().getY())); 
    } 

    public static void drawTriangulation(Graphics2D gr,List<Point3D> shape){ 
     if(shape==null) 
      return; 
     Iterator<Point3D> iter=shape.iterator(); 
     Point3D from=null; 
     Point3D to=null; 
     while(iter.hasNext()){ 
      from=iter.next(); 
      if(iter.hasNext()){ 
       to=iter.next(); 
       GraphicUtil.drawLine(gr, new Line3D(from,to)); 
       if(iter.hasNext()){ 
        from=iter.next(); 
        GraphicUtil.drawLine(gr, new Line3D(from,to));     
       } 
      } 
     }  
    } 
}