引言
网上很少有贝塞尔曲面运算的例子,大多都是OpenGL的,我自己写了一个,共需要的朋友参考一下o(∩_∩)o...
思路
截图
代码
package
com.cg4hj.chapter05.beziersurface;
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import com.cg4hj.utils.Point3D;
@SuppressWarnings( " serial " )
public class BezierSurface extends JFrame {
public BezierSurface() {
super("Bezier Surfaces");
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
System.exit(0);
}
});
add("Center", new CvBezierSurface());
setSize(800,600);
setVisible(true);
}
public static void main(String[] args) {
new BezierSurface();
}
}
@SuppressWarnings( " serial " )
class CvBezierSurface extends Canvas {
private int maxX, maxY;
private double rWidth = 10.0D;
private double rHeight = 10.0D;
private double pixelWidth, pixelHeight;
private int srcCount = 4;
private int dstCount = 40;
private Point3D[][] src = new Point3D[srcCount][srcCount];
private Point3D[][] dst = new Point3D[dstCount][dstCount];
{
for (int i = 0; i < srcCount; i++) {
for (int j = 0; j < srcCount; j++) {
src[i][j] = new Point3D();
}
}
for (int i = 0; i < dstCount; i++) {
for (int j = 0; j < dstCount; j++) {
dst[i][j] = new Point3D();
}
}
}
private void initps() {
for (int i = 0; i < srcCount; i++) {
for (int j = 0; j < srcCount; j++) {
src[i][j].x = random();
src[i][j].y = random();
src[i][j].z = random();
}
}
}
private double random() {
return Math.random() * 10;
}
public CvBezierSurface() {
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent evt) {
repaint();
}
});
}
private int iX(double x) {
return (int)Math.round(x / pixelWidth);
}
private int iY(double y) {
return (int)Math.round(maxY - y / pixelHeight);
}
private void initgr() {
Dimension d = getSize();
maxX = d.width - 1;
maxY = d.height - 1;
pixelWidth = rWidth / maxX;
pixelHeight = rHeight / maxY;
}
public void paint(Graphics g) {
initgr();
initps();
int left = iX(0), right = iX(rWidth),
bottom = iY(0), top = iY(rHeight);
g.drawRect(left, top, right - left, bottom - top);
drawBezierSurface();
}
private void drawBezierSurface() {
Graphics g = getGraphics();
double mui, muj, bi = 0, bj = 0;
for (int i = 0; i < dstCount; i++) {
mui = (i) / (double)(dstCount - 1);
for (int j = 0; j < dstCount; j++) {
muj = (j) / (double)(dstCount - 1);
dst[i][j].x = 0;
dst[i][j].y = 0;
dst[i][j].z = 0;
for (int ki = 0; ki < srcCount; ki++) {
bi = bezierBlendFunction(ki,mui,srcCount - 1);
for (int kj = 0; kj < srcCount; kj++) {
bj = bezierBlendFunction(kj,muj,srcCount - 1);
dst[i][j].x += (src[ki][kj].x * bi * bj);
dst[i][j].y += (src[ki][kj].y * bi * bj);
dst[i][j].z += (src[ki][kj].z * bi * bj);
}
}
}
}
for (int i = 0; i < dstCount; i++) {
for (int j = 0; j < dstCount; j++) {
if (j != dstCount - 1) {
g.drawLine(iX(dst[i][j].x), iY(dst[i][j].y), iX(dst[i][j+1].x), iY(dst[i][j+1].y));
}
if (i != dstCount - 1) {
g.drawLine(iX(dst[i][j].x), iY(dst[i][j].y), iX(dst[i + 1][j].x), iY(dst[i + 1][j].y));
}
}
}
}
private double bezierBlendFunction(int k, double mu, int n) {
int nn = n, kn = k, nkn = n - k;
double blend = 1;
while (nn >= 1) {
blend *= nn;
nn = nn - 1;
if (kn > 1) {
blend /= (double)kn;
kn--;
}
if (nkn > 1) {
blend /= (double)nkn;
nkn--;
}
}
if (k > 0) {
blend *= Math.pow(mu, (double)k);
}
if (n - k > 0) {
blend *= Math.pow(1 - mu, (double)(n - k));
}
return blend;
}
}
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import com.cg4hj.utils.Point3D;
@SuppressWarnings( " serial " )
public class BezierSurface extends JFrame {
public BezierSurface() {
super("Bezier Surfaces");
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
System.exit(0);
}
});
add("Center", new CvBezierSurface());
setSize(800,600);
setVisible(true);
}
public static void main(String[] args) {
new BezierSurface();
}
}
@SuppressWarnings( " serial " )
class CvBezierSurface extends Canvas {
private int maxX, maxY;
private double rWidth = 10.0D;
private double rHeight = 10.0D;
private double pixelWidth, pixelHeight;
private int srcCount = 4;
private int dstCount = 40;
private Point3D[][] src = new Point3D[srcCount][srcCount];
private Point3D[][] dst = new Point3D[dstCount][dstCount];
{
for (int i = 0; i < srcCount; i++) {
for (int j = 0; j < srcCount; j++) {
src[i][j] = new Point3D();
}
}
for (int i = 0; i < dstCount; i++) {
for (int j = 0; j < dstCount; j++) {
dst[i][j] = new Point3D();
}
}
}
private void initps() {
for (int i = 0; i < srcCount; i++) {
for (int j = 0; j < srcCount; j++) {
src[i][j].x = random();
src[i][j].y = random();
src[i][j].z = random();
}
}
}
private double random() {
return Math.random() * 10;
}
public CvBezierSurface() {
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent evt) {
repaint();
}
});
}
private int iX(double x) {
return (int)Math.round(x / pixelWidth);
}
private int iY(double y) {
return (int)Math.round(maxY - y / pixelHeight);
}
private void initgr() {
Dimension d = getSize();
maxX = d.width - 1;
maxY = d.height - 1;
pixelWidth = rWidth / maxX;
pixelHeight = rHeight / maxY;
}
public void paint(Graphics g) {
initgr();
initps();
int left = iX(0), right = iX(rWidth),
bottom = iY(0), top = iY(rHeight);
g.drawRect(left, top, right - left, bottom - top);
drawBezierSurface();
}
private void drawBezierSurface() {
Graphics g = getGraphics();
double mui, muj, bi = 0, bj = 0;
for (int i = 0; i < dstCount; i++) {
mui = (i) / (double)(dstCount - 1);
for (int j = 0; j < dstCount; j++) {
muj = (j) / (double)(dstCount - 1);
dst[i][j].x = 0;
dst[i][j].y = 0;
dst[i][j].z = 0;
for (int ki = 0; ki < srcCount; ki++) {
bi = bezierBlendFunction(ki,mui,srcCount - 1);
for (int kj = 0; kj < srcCount; kj++) {
bj = bezierBlendFunction(kj,muj,srcCount - 1);
dst[i][j].x += (src[ki][kj].x * bi * bj);
dst[i][j].y += (src[ki][kj].y * bi * bj);
dst[i][j].z += (src[ki][kj].z * bi * bj);
}
}
}
}
for (int i = 0; i < dstCount; i++) {
for (int j = 0; j < dstCount; j++) {
if (j != dstCount - 1) {
g.drawLine(iX(dst[i][j].x), iY(dst[i][j].y), iX(dst[i][j+1].x), iY(dst[i][j+1].y));
}
if (i != dstCount - 1) {
g.drawLine(iX(dst[i][j].x), iY(dst[i][j].y), iX(dst[i + 1][j].x), iY(dst[i + 1][j].y));
}
}
}
}
private double bezierBlendFunction(int k, double mu, int n) {
int nn = n, kn = k, nkn = n - k;
double blend = 1;
while (nn >= 1) {
blend *= nn;
nn = nn - 1;
if (kn > 1) {
blend /= (double)kn;
kn--;
}
if (nkn > 1) {
blend /= (double)nkn;
nkn--;
}
}
if (k > 0) {
blend *= Math.pow(mu, (double)k);
}
if (n - k > 0) {
blend *= Math.pow(1 - mu, (double)(n - k));
}
return blend;
}
}