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

📄 render3d.java

📁 java写的3D程序,src目录下有其源程序.
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
	}
	
	public void compile() {
		RenderObject renderObject = render.renderObject;
		Canvas3D canvas = render.canvas;
		int height = canvas.getImage().getHeight();
		int width = canvas.getImage().getWidth();
		bucket = new LinkedList[height];
		
		for(int i=0; i<renderObject.faceCount(); i++) {
			Facelet f = renderObject.getFace(i);
			//寻找多边形的范围
			Vector3d vex = renderObject.getVertex(f.vertexs[0]);
			int minY = (int)Math.round(vex.y), minX = (int)Math.round(vex.x);
			int maxY = (int)Math.round(vex.y), maxX = (int)Math.round(vex.x);
			double maxZ = vex.z, minZ = vex.z;
			for(int j=1; j<f.vertexs.length; j++) {
				vex = renderObject.getVertex(f.vertexs[j]);
				if(minY > (int)Math.round(vex.y)) minY = (int)Math.round(vex.y);
				if(maxY < (int)Math.round(vex.y)) maxY = (int)Math.round(vex.y);
				if(minX > (int)Math.round(vex.x)) minX = (int)Math.round(vex.x);
				if(maxX < (int)Math.round(vex.x)) maxX = (int)Math.round(vex.x);
				if(minZ > vex.z) minZ = vex.z;
				if(maxZ < vex.z) maxZ = vex.z;
			}
			//裁掉完全没有映射到缓存中的面
			if(minY > height-1 || maxY < 0 || minX > width-1 || maxX < 0) continue;
			
			//加入有效的多边形
			if(minY < 0) minY = 0;
			if(minY > maxY) continue;
			FaceYItem item = createItem(f, i, minY, maxY, minZ, maxZ);
			if(item == null) {
				continue;	//垂直XOY平面
			}
			if(bucket[minY] == null) bucket[minY] = new LinkedList();
			bucket[minY].addLast(item);		
		}
	}
}

/** 有效边对类*/
class AETItem {
	double xl, xr;
	int maxYL, maxYR;
	double ddxl, ddxr;
	double zl, ddzx, ddzy;
	Vector3d cl, cr;
	Vector3d ddcl, ddcr;
	int faceIndex;
	FaceYItem faceYItem;
	
	public AETItem() {
	}
	
	public AETItem(double xl, int maxYL, double ddxl, 
				   double xr, int maxYR, double ddxr,
				   double zl, double ddzx, double ddzy, 
				   Vector3d cl, Vector3d cr, Vector3d ddcl, Vector3d ddcr,
				   int faceIndex, FaceYItem faceYItem) {
		this.xl = xl;	this.maxYL = maxYL;		this.ddxl = ddxl;
		this.xr = xr;	this.maxYR = maxYR;		this.ddxr = ddxr;
		this.zl = zl;	this.ddzx = ddzx;		this.ddzy = ddzy;
		this.cl = cl;	this.cr = cr;
		this.ddcl = ddcl;	this.ddcr = ddcr;
		this.faceIndex = faceIndex;
		this.faceYItem = faceYItem;
	}
}

class Render3D {
	protected Canvas3D canvas;
	protected RenderObject renderObject;
	protected FaceYBucket faceYBucket = new FaceYBucket(this);
	protected LinkedList aptList = new LinkedList();
	protected LinkedList aetList = new LinkedList();
	protected double zbuf[];		//深度缓存
	protected int cbuf[];		//颜色缓存
	protected double cosbuf[];	//视角缓存
	protected Color bkColor;	//背景色
	protected int bkRGB;		
	
	
	public Render3D(Canvas3D canvas) {
		this.canvas = canvas;
		renderObject = new RenderObject(canvas);
		
		bkColor = new Color(0, 0, 0);
		bkRGB = bkColor.getAlpha()<<24 | bkColor.getRed()<<16 | 
			  bkColor.getGreen()<<8 | bkColor.getBlue();
	}
	
	private AETItem getAETItem(int faceIndex) {
		ListIterator it = aetList.listIterator();
		while(it.hasNext()) {
			AETItem aetItem = (AETItem)it.next();
			if(aetItem.faceIndex == faceIndex) return aetItem;
		}
		
		return null;
	}
	
	private void renderLine(int scanY) {
		int i, start, end;
		double z;
		BufferedImage image = canvas.getImage();
		int width = image.getWidth();
		for(i=0; i<width; i++) {
			zbuf[i] = Double.MAX_VALUE;
			cbuf[i] = bkRGB;
			cosbuf[i] = 1;
		}
		
		
		ListIterator it = aetList.listIterator();
		
		while(it.hasNext()) {
			AETItem aetItem = (AETItem)it.next();
			Facelet face = renderObject.getFace(aetItem.faceIndex);
			FaceYItem faceYItem = aetItem.faceYItem;
			start = (int)Math.round(aetItem.xl);
			if(start < 0) start = 0;
			end = (int)Math.round(aetItem.xr);
			if(end >= width) end = width-1;
			
			int ddx = end-start;
			if(ddx <= 0) continue;
			
			z = aetItem.zl-(start-aetItem.xl)*aetItem.ddzx;
			if(z < faceYItem.minZ) z = faceYItem.minZ;
			if(z > faceYItem.maxZ) z = faceYItem.maxZ;
			Vector3d c = new Vector3d(aetItem.cl);
			Vector3d ddcx = new Vector3d((aetItem.cl.x-aetItem.cr.x)/ddx,
										 (aetItem.cl.y-aetItem.cr.y)/ddx,
										 (aetItem.cl.z-aetItem.cr.z)/ddx);
			c.x = c.x-(start-aetItem.xl)*ddcx.x;
			c.y = c.y-(start-aetItem.xl)*ddcx.y;
			c.z = c.z-(start-aetItem.xl)*ddcx.z;
			
			double cosv = renderObject.getCosv(aetItem.faceIndex);
			int step = 1;//end-start;
			for(i=start; i<=end; i+=step) {
				//double zz = -(faceYItem.a*i+faceYItem.b*scanY+faceYItem.d)/faceYItem.c;
				double dz = z-zbuf[i];
				//if((dz <= 0.5 && cosv < cosbuf[i]) || dz < -0.5) {
				if(dz <= 0) {
					cbuf[i] = (int)255<<24 | ((int)c.x)<<16 | 
		  				  ((int)c.y)<<8 | ((int)c.z);
		  			cosbuf[i] = cosv;
					zbuf[i] = z;
				}
				z -= aetItem.ddzx*(step);
				if(z < faceYItem.minZ) z = faceYItem.minZ;
				if(z > faceYItem.maxZ) z = faceYItem.maxZ;
				c.x -= ddcx.x;
				c.y -= ddcx.y;
				c.z -= ddcx.z;
			}
		}
		
		image.setRGB(0, scanY, width, 1, cbuf, 0, width);
	}
	
	private void scanAPT(int scanY) {
		ListIterator it = aptList.listIterator();
		while(it.hasNext()) {
			FaceYItem fItem = (FaceYItem)it.next();
			LinkedList eList = fItem.edgeYBucket.get(scanY);
			if(eList != null) {
				AETItem aetItem = getAETItem(fItem.faceIndex);
				if(aetItem == null)	{ //首次加入该多边形的有效边(必然存在2条)
					EdgeYItem e0 = (EdgeYItem)eList.get(0);
					EdgeYItem e1 = (EdgeYItem)eList.get(1);
					if((e0.cx > e1.cx) ||
					   (e0.cx == e1.cx && e0.ddx < e1.ddx)) {
						EdgeYItem e = e0;
						e0 = e1;
						e1 = e;
					}
					
					aetItem = new AETItem(e0.cx, e0.maxY, e0.ddx,
										  e1.cx, e1.maxY, e1.ddx,
										  e0.z, fItem.a/fItem.c, fItem.b/fItem.c,
										  e0.color, e1.color, e0.ddcolor, e1.ddcolor, 
										  fItem.faceIndex, fItem);
					aetList.addLast(aetItem);
				}
				else {
					EdgeYItem e = (EdgeYItem)eList.get(0);
					if(aetItem.xl < 0)	{ //左边被删去
						aetItem.xl = e.cx;
						aetItem.maxYL = e.maxY;
						aetItem.ddxl = e.ddx;
						aetItem.zl = e.z;
						aetItem.cl = e.color;
						aetItem.ddcl = e.ddcolor;
					}
					else {
						aetItem.xr = e.cx;
						aetItem.maxYR = e.maxY;
						aetItem.ddxr = e.ddx;
						aetItem.cr = e.color;
						aetItem.ddcr = e.ddcolor;	
					}
				}		
			}
		}
	}
	
	private void updateAET(int scanY) {
		ListIterator it = aetList.listIterator();
		while(it.hasNext()) {
			AETItem aetItem = (AETItem)it.next();
			Facelet face = renderObject.getFace(aetItem.faceIndex);
			FaceYItem faceYItem = aetItem.faceYItem;
			
			if(aetItem.faceIndex == 1) {
				aetItem = aetItem;
			}
			if((aetItem.maxYL == scanY && 
			   aetItem.maxYL < aetItem.faceYItem.maxY) ||
			   aetItem.maxYL < scanY) {
				aetItem.xl = Double.NEGATIVE_INFINITY;	//置为-无穷表示删除
			}
			if((aetItem.maxYR == scanY && 
			   aetItem.maxYR < aetItem.faceYItem.maxY) ||
			   aetItem.maxYR < scanY) {
				aetItem.xr = Double.NEGATIVE_INFINITY;	//置为-无穷表示删除
			}
			
			//如果左右两边均被删除则删除该项目
			if(aetItem.xl == Double.NEGATIVE_INFINITY && 
			   aetItem.xr == Double.NEGATIVE_INFINITY) {
				it.remove();	
				continue ;
			}
			
			if(aetItem.xl != Double.NEGATIVE_INFINITY) {
				aetItem.xl -= aetItem.ddxl;
				aetItem.zl += (aetItem.ddzx*aetItem.ddxl - aetItem.ddzy);
				if(aetItem.zl < faceYItem.minZ) aetItem.zl = faceYItem.minZ;
				if(aetItem.zl > faceYItem.maxZ) aetItem.zl = faceYItem.maxZ;
				aetItem.cl.x -= aetItem.ddcl.x;
				aetItem.cl.y -= aetItem.ddcl.y;
				aetItem.cl.z -= aetItem.ddcl.z;
			}
			if(aetItem.xr != Double.NEGATIVE_INFINITY) {
				aetItem.xr -= aetItem.ddxr;
				aetItem.cr.x -= aetItem.ddcr.x;
				aetItem.cr.y -= aetItem.ddcr.y;
				aetItem.cr.z -= aetItem.ddcr.z;
			}
		}	
	}
	
	private void scan() {
		int height = canvas.getImage().getHeight();
		ListIterator it;
		for(int i=0; i<height; i++) {
			//(1)删除已经扫描完成的多边形
			it = aptList.listIterator();
			while(it.hasNext()) {
				FaceYItem fItem = (FaceYItem)it.next();
				if(fItem.maxY < i) {
					it.remove();
				}
			}
			//(2)如果该扫描线对应有新的多边形加入
			if(faceYBucket.bucket[i] != null)	{ 
				it = faceYBucket.bucket[i].listIterator();
				while(it.hasNext()) {
					FaceYItem fItem = (FaceYItem)it.next();
					fItem.edgeYBucket.compile();
					aptList.addLast(fItem);
				}
				//aptList.addAll(faceYBucket.bucket[i]);
			}
			
			//(3)检查更新有效边表
			updateAET(i);
			
			//(4)扫描有效面表apt中的多边形Y桶,看是否有新边对,补充有效边表aet
			scanAPT(i);
			
			//(5)渲染当前扫描线
			renderLine(i);
		}
	}
	
	public void compile() {
		BufferedImage image = canvas.getImage();
		zbuf = new double[image.getWidth()];
		cbuf = new int[image.getWidth()];
		cosbuf = new double[image.getWidth()];
		
		Camera camera = canvas.getCamera();
		camera.refresh();
		
		aptList.clear();
		aetList.clear();
		
		renderObject.compile();
		
		faceYBucket.compile();
		
		scan();
	}
}

⌨️ 快捷键说明

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