⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 render3d.java

📁 java写的3D程序,src目录下有其源程序.
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package myprojects.graph3dapp;

import java.awt.*;
import java.util.*;
import java.awt.image.*;

class RenderObject extends GraphObject3D {
	protected Canvas3D canvas;
	
	protected Vector3d vertexHeap[];
	protected Facelet faceHeap[];
	protected double cosvHeap[];
	protected int vertexCount = 0;
	protected int faceCount = 0;
	
	public RenderObject(Canvas3D canvas) {
		this.canvas = canvas;
	}
	
	public Vector3d getVertex(int index) {
		return vertexHeap[index];
	}
	
	public int vertexCount() {
		return vertexCount;
	}
	
	public Facelet getFace(int index) {
		return faceHeap[index];
	}
	
	public double getCosv(int index) {
		return cosvHeap[index];
	}
	
	public int faceCount() {
		return faceCount;
	}
	
	protected void applyColor(int destIndex, Facelet dest, Facelet src) {
		Matrix3d transMatrix = src.getObject().getTransMatrix();
		Color ca = canvas.atmosphereColor;
		Material mat = src.material;
		Vector3d n = dest.normalize();
		Vector3d vpn = canvas.camera.vpn;
		vpn.normalize();
		cosvHeap[destIndex] = vpn.dot(n);
		Light light = canvas.light;
		
		for(int i=0; i<src.vertexs.length; i++) {
			Vector3d vex = dest.getVertex(i);
			Vector3d l = Vector3d.sub(light.position, vex);
			l.normalize();
			Vector3d v = Vector3d.sub(canvas.camera.vrp, vex);
			v.normalize();
			Vector3d h = Vector3d.add(l, v);
			h.scale(0.5f);
			h.normalize();
			double cosd = l.dot(n);
			if(cosd < 0) cosd = 0;
			double cossn = (double)Math.pow(h.dot(n), mat.kn);
			int r = (int)Math.round(ca.getRed()*mat.ka.x + 
					light.color.getRed()*(mat.kd.x*cosd + mat.ks.x*cossn));
			if(r < 0) r = 0;
			if(r > 255) r = 255;
			
			int g = (int)Math.round(ca.getGreen()*mat.ka.y + 
					light.color.getGreen()*(mat.kd.y*cosd + mat.ks.y*cossn));
			if(g < 0) g = 0;
			if(g > 255) g = 255;
			
			int b = (int)Math.round(ca.getBlue()*mat.ka.z + 
					light.color.getBlue()*(mat.kd.z*cosd + mat.ks.z*cossn));
			if(b < 0) b = 0;
			if(b > 255) b = 255;
			dest.colors[i] = new Color(r, g, b);
		}
	}
	
	public void compile() {
		int i;
		LinkedList objectList = canvas.getObjectList();
		ListIterator it = objectList.listIterator();
		vertexCount = 0;
		faceCount = 0;
		while(it.hasNext()) {
			GraphObject3D object = (GraphObject3D)(it.next());
			vertexCount += object.vertexCount();
			faceCount += object.faceCount();
		}
		
		vertexHeap = new Vector3d[vertexCount];
		faceHeap = new Facelet[faceCount];
		cosvHeap = new double[faceCount];
		
		it = objectList.listIterator();
		Camera camera = canvas.getCamera();
		
		int vertexIndex = 0;
		int faceIndex = 0;
		while(it.hasNext()) {
			GraphObject3D object = (GraphObject3D)(it.next());
			for(i=0; i<object.vertexCount(); i++) {
				vertexHeap[vertexIndex+i] = Vector3d.mulMatrix(object.getVertex(i),
															   object.getTransMatrix());
				//vertexHeap[vertexIndex+i] = camera.project(object.getVertex(i),
				//										   object.getTransMatrix());
				//System.out.println(vertexHeap[vertexIndex+i]);
			}
			for(i=0; i<object.faceCount(); i++) {
				Facelet f = object.getFace(i);
				faceHeap[faceIndex+i] = new Facelet(this, f.vertexs[0]+vertexIndex,
													f.vertexs[1]+vertexIndex, 
													f.vertexs[2]+vertexIndex);
				applyColor(faceIndex+i, faceHeap[faceIndex+i], f);
			}
			
			for(i=0; i<object.vertexCount(); i++) {
				vertexHeap[vertexIndex+i] = camera.project(vertexHeap[vertexIndex+i]);
			}
			vertexIndex += object.vertexCount();
			faceIndex += object.faceCount();
		}
	}
}

/** 边Y桶数据项*/
class EdgeYItem {
	public int minY;		//较小端y值图像映射坐标
	public int maxY;		//较大端y值图像映射坐标
	public double ddx;		//x增量
	public int cx;			//y较小端x图像映射坐标
	public double z;			//y较小端在观察坐标系中的深度
	public Vector3d color;		//y较小端颜色
	public Vector3d ddcolor;//颜色增量
	
	public EdgeYItem() {
	}
	
	public EdgeYItem(int minY, int maxY, double ddx, int cx, double z,
					 Vector3d color, Vector3d ddcolor) {
		this.minY = minY;
		this.maxY = maxY;
		this.ddx = ddx;
		this.cx = cx;
		this.z = z;
		this.color = color;
		this.ddcolor = ddcolor;
	}
}

/** 边Y桶类*/
class EdgeYBucket {
	protected Render3D render;
	protected FaceYItem faceYItem;
	protected LinkedList bucket[];
	
	public EdgeYBucket(Render3D render, FaceYItem faceYItem) {
		this.render = render;
		this.faceYItem = faceYItem;
	}
	
	private void swapVector(Vector3d v0, Vector3d v1) {
		double x = v0.x;
		v0.x = v1.x;
		v1.x = x;
		double y = v0.y;
		v0.y = v1.y;
		v1.y = y;
		double z = v0.z;
		v0.z = v1.z;
		v1.z = z;
	}
	
	private EdgeYItem createItem(int v0, int v1, int ci0, int ci1) {
		Facelet face = faceYItem.face;
		RenderObject object = (RenderObject)(face.getObject());
		//注意:因为后面的操作可能会修改顶点的内容,所以必须构造新的对象,用新对象操作
		Vector3d vex0 = new Vector3d(object.getVertex(v0));
		vex0.x = Math.round(vex0.x);
		vex0.y = Math.round(vex0.y);
		vex0.z = -(faceYItem.a*vex0.x+faceYItem.b*vex0.y+faceYItem.d)/faceYItem.c;
		Vector3d c0 = new Vector3d(face.colors[ci0].getRed(), face.colors[ci0].getGreen(),
							 	   face.colors[ci0].getBlue());
		Vector3d vex1 = new Vector3d(object.getVertex(v1));
		vex1.x = Math.round(vex1.x);
		vex1.y = Math.round(vex1.y);
		vex1.z = -(faceYItem.a*vex1.x+faceYItem.b*vex1.y+faceYItem.d)/faceYItem.c;
		Vector3d c1 = new Vector3d(face.colors[ci1].getRed(), face.colors[ci1].getGreen(),
							 	   face.colors[ci1].getBlue());
		
		//如果该边是水平的则无须加入此时ddx为无穷大
		if((int)vex0.y == (int)vex1.y) return null;	
		
		if(vex0.y > vex1.y) {
			swapVector(vex0, vex1);
			swapVector(c0, c1);
		}
		
		//如果该边根本不在缓冲扫描范围内放弃
		if((int)vex0.y > faceYItem.maxY) return null;	
		if((int)vex1.y < faceYItem.minY) return null;
		
		double ddx = -(vex1.x-vex0.x)/(vex1.y-vex0.y);
		Vector3d ddcolor = new Vector3d();
		ddcolor.x = -(double)(c1.x-c0.x)/(vex1.y-vex0.y);
		ddcolor.y = -(double)(c1.y-c0.y)/(vex1.y-vex0.y);
		ddcolor.z = -(double)(c1.z-c0.z)/(vex1.y-vex0.y);
		
		if((int)(vex0.y) < faceYItem.minY) {			
			double dy = faceYItem.minY-vex0.y;
			vex0.x = Math.round(vex0.x-dy*ddx);
			vex0.y = faceYItem.minY;
			if((int)vex0.y >= (int)vex1.y) return null;	//如果修正后端点重合则放弃该边
			vex0.z = -(faceYItem.a*vex0.x+faceYItem.b*vex0.y+faceYItem.d)/faceYItem.c;
			c0.x = c0.x-dy*ddcolor.x;
			c0.y = c0.y-dy*ddcolor.y;
			c0.z = c0.z-dy*ddcolor.z;
		}
		
		return new EdgeYItem((int)vex0.y, (int)vex1.y, ddx, (int)vex0.x, vex0.z,
							 c0, ddcolor);
	}
	
	public void compile() {
		bucket = new LinkedList[faceYItem.maxY-faceYItem.minY+1];
		Facelet face = faceYItem.face;
		
		if(faceYItem.faceIndex == 1) {
			faceYItem.faceIndex = 1;
		}
		EdgeYItem item = createItem(face.vertexs[0], face.vertexs[1], 0, 1);
		if(item != null) {
			int index = item.minY-faceYItem.minY;
			if(bucket[index] == null) bucket[index] = new LinkedList();
			bucket[index].addLast(item);
		}
		
		item = createItem(face.vertexs[1], face.vertexs[2], 1, 2);
		if(item != null) {
			int index = item.minY-faceYItem.minY;
			if(bucket[index] == null) bucket[index] = new LinkedList();
			bucket[index].addLast(item);
		}
		
		item = createItem(face.vertexs[2], face.vertexs[0], 2, 0);
		if(item != null) {
			int index = item.minY-faceYItem.minY;
			if(bucket[index] == null) bucket[index] = new LinkedList();
			bucket[index].addLast(item);
		}
	}
	
	/** 根据扫描线y坐标返回桶中的边表*/
	public LinkedList get(int scanY) {
		return bucket[scanY-faceYItem.minY];
	}
}

/** 多边形Y桶数据项*/
class FaceYItem {
	public int faceIndex = 0;
	public int minY = 0, maxY = 0;
	public double minZ = 0, maxZ = 0;
	public double a, b, c, d;
	public EdgeYBucket edgeYBucket;
	public Facelet face;
	
	public FaceYItem() {
	}
	
	public String toString() {
		return	"("+String.valueOf(faceIndex)+", "+String.valueOf(minY)+", "+
				String.valueOf(maxY)+", "+String.valueOf(a)+", "+
				String.valueOf(b)+", "+String.valueOf(c)+", "+
				String.valueOf(d)+")";
	}
}

/** 多边形Y桶类*/
class FaceYBucket {
	protected Render3D render;
	protected LinkedList bucket[];
	
	public FaceYBucket(Render3D render) {
		this.render = render;
	}
	
	private FaceYItem createItem(Facelet face, int faceIndex, int minY, int maxY,
								 double minZ, double maxZ) {
		Vector3d n = face.normalize();
		if(Math.abs(n.z) < 0.0005) return null;	//如果面垂直于XOY平面,简单起见放弃该面
		
		FaceYItem item = new FaceYItem();
		item.faceIndex = faceIndex;
		item.minY = minY;
		item.maxY = maxY;
		item.a = n.x;
		item.b = n.y;
		item.c = n.z;
		item.minZ = minZ;
		item.maxZ = maxZ;
		
		Vector3d v0 = face.getVertex(0);
		item.d = -v0.x*n.x-v0.y*n.y-v0.z*n.z;	
		item.face = face;
		item.edgeYBucket = new EdgeYBucket(render, item);
		//item.edgeYBucket.compile();	//创建边Y桶
		
		return item;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -