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

📄 polygon3d.java

📁 一个java 3D程序的源代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
import java.awt.*;
import java.awt.image.*;
import javax.imageio.ImageIO;


public class polygon3D{
	public vector[] tempVertix;
	public vector[] vertix2D;
	public vector[] vertix3D;
	public int[] vertixSpecular;
	public vector[] vertixNormals;
	public vector[] temp_vertixNormals;
	public static vector[] tempVectors;
	public vector normal, realNormal;
	public vector centre, realCentre;
	public static int[] xLow, xHigh, s_left, s_right, xChange_left, xChange_right;
	public int[] xLow_transprent, xHigh_transprent;
	public int height;
	public int topIndex;
	public boolean visible;
	public Rectangle bound;
	public double zMax, zMin;
	public texture myTexture;
	public double textureScaleX, textureScaleY;
	public vector W, O, V, U, A, B, C;
	public double aDotW, bDotW, cDotW;
	public double scaleX = 1, scaleY = 1;
	public int textureWidth, textureHeight, heightMask, widthMask, widthBits, heightBits;
	public int X, Y, X1, Y1, dx, dy, textureIndex;
	public int visibleCount;
	public vector origin, rightEnd, bottomEnd;
	public int L;
	public vector view = new vector(0,0,1);
	public int end = 0;
	public int start = 479;
	public boolean isLightMap;
	public int[] Texture;
	public int Z_length;
	public double A_offset, B_offset, C_offset;
	public boolean faceVerticalPolygon;
	public int BigX, BigY, BigDx, BigDy;
	public boolean gouraudShading;
	public int diffuse_I;
	public int ambient_I;
	public int roughness;
	public boolean waterSurface;


	public polygon3D(vector[] vertix3D, vector origin,  vector  rightEnd, vector bottomEnd,  texture myTexture){
		L = vertix3D.length;
		Z_length = vector.Z_length;
		tempVectors = new vector[4];
		for(int i = 0; i < tempVectors.length; i++)
			if(tempVectors[i] == null)
				tempVectors[i] = new vector();

		this.vertix3D = vertix3D;

		tempVertix = new vector[L];

		for(int i = 0; i < L; i++){
			tempVertix[i] = new vector();
			tempVertix[i].set(vertix3D[i]);
		}

		centre =  new vector(0,0,0);
		testVisibility();

		if(Math.abs(normal.y) > 0.99)
			faceVerticalPolygon = true;
		else
			faceVerticalPolygon = false;


		realNormal = new vector(0,0,0);
		realNormal.set(normal);

		realCentre = new vector(0,0,0);
		realCentre.set(centre);

		this.myTexture = myTexture;

		if(myTexture == null)
			return;

		ambient_I = 60;

		findDiffuse();

		Texture = myTexture.Texture;

		this.origin = origin;
		this.rightEnd = rightEnd;
		this.bottomEnd = bottomEnd;

		textureWidth = myTexture.width;
		textureHeight = myTexture.height;
		heightMask = myTexture.heightMask;
		widthMask = myTexture.widthMask;
		widthBits = myTexture.widthBits;
		heightBits = myTexture.heightBits;

		findTextureScale();

		W = new vector(); O = new vector(); V = new vector(); U = new vector(); A = new vector(); B = new vector(); C = new vector();

		vertix2D = new vector[L+1];
		for(int i = 0; i < vertix2D.length; i++)
			vertix2D[i] = new vector(0,0,0);

		vertixSpecular = new int[L+1];

		temp_vertixNormals = new vector[L+1];
		for(int i = 0; i < L+1; i++)
			temp_vertixNormals[i] = new vector(0,0,0);

		vertixNormals = new vector[L];
		for(int i = 0; i < L; i++)
			vertixNormals[i] = new vector(0,0,0);

		if(xLow == null){
			xLow = new int[480];
			xHigh = new int[480];
			s_left= new int[480];
			s_right = new int[480];
			xChange_left = new int[480];
			xChange_right = new int[480];
		}
	}


	public final void findTextureScale(){
		tempVectors[0].set(origin);
		tempVectors[0].subtract(rightEnd);
		double l = tempVectors[0].getLength();
		textureScaleX = l/myTexture.width;

		tempVectors[0].set(origin);
		tempVectors[0].subtract(bottomEnd);
		l = tempVectors[0].getLength();
		textureScaleY = l/myTexture.height;
	}

	public static polygon3D createPolygon(vector[] vertix3D, vector origin,  vector  rightEnd, vector bottomEnd,  texture myTexture, double textureX, double textureY, double scaleX, double scaleY){
		vector x = origin.myClone();
		x.subtract(rightEnd);
		x.scale(textureX);
		vector y = origin.myClone();
		y.subtract(bottomEnd);
		y.scale(textureY);

		origin.add(x);
		bottomEnd.add(x);
		rightEnd.add(x);
		origin.add(y);
		bottomEnd.add(y);
		rightEnd.add(y);

		polygon3D p = new polygon3D(vertix3D,  origin, rightEnd, bottomEnd, myTexture);
		p.scaleX = scaleX;
		p.scaleY = scaleY;
		return p;
	}



	public final void update(){
		for(int i = 0; i < L; i++){
			tempVertix[i].set(vertix3D[i]);
			tempVertix[i].subtract(camera.position);
			tempVertix[i].rotate_XZ();
			tempVertix[i].rotate_YZ();
			tempVertix[i].updateLocation();
		}
		testVisibility();
	}

	public final void findDiffuse(){
		tempVectors[0].set(LightSource.s1_);
		tempVectors[0].subtract(realCentre);
		tempVectors[0].unit();
		double temp = tempVectors[0].dot(realNormal);
		if(temp <= -0.5)
			diffuse_I = ambient_I;
		else
			diffuse_I = ambient_I + (int)(128*(temp+0.5));

	}

	public final void findSpecular(){
		if(diffuse_I == ambient_I){
			for(int i = 0; i < vertixSpecular.length; i ++)
				vertixSpecular[i] = 0;
			return;
		}

		for(int i = 0; i < visibleCount; i++){
			tempVectors[2].set(temp_vertixNormals[i]);
			tempVectors[2].rotate_XZ();
			tempVectors[2].rotate_YZ();

			tempVectors[0].set(LightSource.s1);
			tempVectors[0].subtract(vertix2D[i]);
			tempVectors[0].unit();
			tempVectors[1].set(tempVectors[2]);
			tempVectors[1].scale(2*tempVectors[0].dot(tempVectors[1]));
			tempVectors[0].subtract(tempVectors[1]);
			tempVectors[0].scale(-1);

			tempVectors[1].set(0,0,0);
			tempVectors[1].subtract(vertix2D[i]);
			tempVectors[1].unit();

			double temp = tempVectors[1].dot(tempVectors[0]);


			if(temp < 0)
				temp = 0;
			else{
				for(int j = 0; j < roughness; j++)
					temp*=temp;
			}
			vertixSpecular[i] = (int)(176 * temp) << 16;
		}
	}

	public final void findVectorOUV(){
		O.set(origin);
		O.subtract(camera.position);
		O.rotate_XZ(-camera.look_right);
		O.rotate_YZ(camera.look_up);

		U.set(rightEnd);
		U.subtract(camera.position);
		U.rotate_XZ(-camera.look_right);
		U.rotate_YZ(camera.look_up);

		V.set(bottomEnd);
		V.subtract(camera.position);
		V.rotate_XZ(-camera.look_right);
		V.rotate_YZ(camera.look_up);

		U.subtract(O);
		U.unit();
		U.scale(textureScaleX/scaleX);

		V.subtract(O);
		V.unit();
		V.scale(textureScaleY/scaleY);

		A = V.cross(O);
		B = O.cross(U);
		C = U.cross(V);
	}

	public final void testVisibility(){
		visible = false;

		//find normal vector
		tempVectors[0].set(tempVertix[1]);
		tempVectors[0].subtract(tempVertix[0]);
		tempVectors[1].set(tempVertix[2]);
		tempVectors[1].subtract(tempVertix[1]);
		normal = tempVectors[0].cross(tempVectors[1]);
		normal.unit();




		//find centre
		findCentre();

		//test whether all vertix is in front of viwer's plane
		for(int i = 0; i < tempVertix.length; i++){
			if(tempVertix[i].z > 0){
				visible = true;
				break;
			}
		}


		//test whether the polygon is within view angle
		if(visible){
			if(view.dot(normal) >= 0.6)
				visible = false;
		}

		//test whether this polygon is facing toward viewer
		if(visible){
			tempVectors[0].set(tempVertix[0]);
			if(tempVectors[0].dot(normal) >= 0)
				visible = false;
		}

		//test whether this polygon is inside the screen
		if(visible){
			find_zMax_zMin();

			visible = camera.screen.intersects(bound);
		}
	}

	public final void findCentre(){
		centre.reset();
		for(int i = 0; i < tempVertix.length; i++)
			centre.add(tempVertix[i]);
		centre.scale(1.0/tempVertix.length);

	}

	public final void find_zMax_zMin(){
		int xMax = tempVertix[0].screenX;
		int xMin = xMax;
		int yMax = tempVertix[0].screenY;
		int yMin = yMax;
		zMax = tempVertix[0].z;
		zMin = zMax;
		for(int i = 1; i < tempVertix.length; i++){
			xMax = Math.max(xMax, tempVertix[i].screenX);
			xMin = Math.min(xMin, tempVertix[i].screenX);
			yMax = Math.max(yMax, tempVertix[i].screenY);
			yMin = Math.min(yMin, tempVertix[i].screenY);
			zMax = Math.max(zMax, tempVertix[i].z);
			zMin = Math.min(zMin, tempVertix[i].z);
		}
		bound = new Rectangle(xMin, yMin, xMax-xMin, yMax-yMin);
	}

	public final void findClipping(){
		visibleCount = 0;
		for(int i = 0; i < L; i++){
			if(tempVertix[i].z >= 0.01){
				vertix2D[visibleCount].set(tempVertix[i]);
				vertix2D[visibleCount].updateLocation();
				temp_vertixNormals[visibleCount].set(vertixNormals[i]);
				visibleCount++;
			} else{
				int index = (i+L - 1)%L;
				if(tempVertix[index].z >= 0.01){
					approximatePoint(visibleCount, tempVertix[i], tempVertix[index]);
					temp_vertixNormals[visibleCount].set(vertixNormals[index]);
					visibleCount++;
				}
				index = (i+1)%L;
				if(tempVertix[index].z >= 0.01){
					approximatePoint(visibleCount, tempVertix[i], tempVertix[index]);
					temp_vertixNormals[visibleCount].set(vertixNormals[index]);
					visibleCount++;
				}
			}
		}
	}


	public final void approximatePoint(int index, vector behindPoint, vector frontPoint){
		tempVectors[0].set(frontPoint.x - behindPoint.x, frontPoint.y - behindPoint.y, frontPoint.z - behindPoint.z);
		tempVectors[0].scale(frontPoint.z/tempVectors[0].z);
		vertix2D[index].set(frontPoint.x, frontPoint.y, frontPoint.z);
		vertix2D[index].subtract(tempVectors[0]);
		vertix2D[index].add(0,0,0.01);
		vertix2D[index].updateLocation();
	}

	public final void scanPolygon(){
		int minX = 0;
		int maxX = 639;
		int minY = 0;
		int maxY = 479;
		start = 479;
		end = 0;
		double temp_ = 0;

		for(int i = 0; i < visibleCount; i++){
			vector v1 = vertix2D[i];
			int s1 = vertixSpecular[i];
			vector v2;
			int s2;
			if(i == visibleCount -1 ){
				v2 = vertix2D[0];
				s2 = vertixSpecular[0];
			}else{
				v2 = vertix2D[i+1];
				s2 = vertixSpecular[i+1];
			}

			boolean downwards = false;


			//ensure v1.y < v2.y;
			if (v1.screenY> v2.screenY) {
				downwards = true;
				vector temp = v1;
				int temp1 = s1;
				v1 = v2;
				s1 = s2;
				v2 = temp;
				s2 = temp1;
			}
			int dy = v2.screenY - v1.screenY;

			// ignore horizontal lines
			if (dy == 0) {
				continue;
			}

			int ds = (s2 - s1)/dy;

			int startY = Math.max(v1.screenY, minY);
			int endY = Math.min(v2.screenY, maxY);

			int startS = s1 + (startY - v1.screenY) * ds;

			if(startY < start )
				start = startY;

			if(endY > end)
				end = endY;

			double dx = v2.screenX - v1.screenX;
			double gradient = dx / dy;

			int temp_x, x;
			temp_ = v1.screenX + (startY - v1.screenY) * gradient;
			// scan-convert this edge (line equation)
			for (int y=startY, s=startS; y<=endY; y++, s+=ds) {
				temp_x = ceil(temp_);
				temp_+=gradient;
				// ensure x within view bounds
				x = Math.min(maxX+1, Math.max(temp_x, minX));
				if(downwards){
					xLow[y] = x;
					s_left[y] = s;
					xChange_left[y] =  x - temp_x;
				}else{
					xHigh[y] = x;
					s_right[y] = s;
					xChange_right[y] = x - temp_x;
				}
			}
		}
		int ds, l;
		for(int i = start; i <= end; i++){
			l = (xHigh[i] - xChange_right[i]) - (xLow[i] - xChange_left[i]);
			if(l == 0)
				continue;
			ds = (s_right[i] - s_left[i])/l;
			s_left[i] = s_left[i] + xChange_left[i]*ds;
			s_right[i] = s_right[i] + xChange_right[i]*ds;
		}
	}

	public final int ceil(double f) {
		if (f > 0) {
			return (int)f + 1;
		}
		else {
		   return (int)f;
		}
	}

	public final void drawTransparent(){
		if(!visible)
			return;

		int texel = 0;
		int r = 0;
		int g = 0;
		int b = 0;
		int temp = 0;
		int theIndex = 0;
		int i = 0;
		int j = 0;
		int k = 0;
		double  length = centre.getLength();
		if(length > 10){
			int scale = 2;
			if(length > 25)
				scale = 3;


			double cDotWInverse;

⌨️ 快捷键说明

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