테스트

aion-server 4.8

Gitteol
최고관리자 · 1 · 💬 0 클론/새로받기
 4.8 61f661d · 1 commits 새로받기(Pull)
game-server/src/com/aionemu/gameserver/geoEngine/math/Ray.java
/*
 * Copyright (c) 2009-2010 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.aionemu.gameserver.geoEngine.math;

import com.aionemu.gameserver.geoEngine.bounding.BoundingVolume;
import com.aionemu.gameserver.geoEngine.collision.Collidable;
import com.aionemu.gameserver.geoEngine.collision.CollisionResults;
import com.aionemu.gameserver.geoEngine.collision.UnsupportedCollisionException;
import com.aionemu.gameserver.geoEngine.utils.TempVars;

/**
 * <code>Ray</code> defines a line segment which has an origin and a direction. That is, a point and an infinite ray is
 * cast from this point. The ray is defined by the following equation: R(t) = origin + t*direction for t >= 0.
 * 
 * @author Mark Powell
 * @author Joshua Slack
 */
public final class Ray implements Cloneable, Collidable {

	/** The ray's begining point. */
	public Vector3f origin;
	/** The direction of the ray. */
	public Vector3f direction;

	public float limit = Float.POSITIVE_INFINITY;

	/**
	 * Constructor instantiates a new <code>Ray</code> object. As default, the origin is (0,0,0) and the direction is
	 * (0,0,0).
	 */
	public Ray() {
		origin = new Vector3f();
		direction = new Vector3f();
	}

	/**
	 * Constructor instantiates a new <code>Ray</code> object. The origin and direction are given.
	 * 
	 * @param origin
	 *          the origin of the ray.
	 * @param direction
	 *          the direction the ray travels in.
	 */
	public Ray(Vector3f origin, Vector3f direction) {
		this.origin = origin;
		this.direction = direction;
	}

	/**
	 * <code>intersectWhere</code> determines if the Ray intersects a triangle defined by the specified points and if so
	 * it stores the point of intersection in the given loc vector.
	 * 
	 * @param v0
	 *          first point of the triangle.
	 * @param v1
	 *          second point of the triangle.
	 * @param v2
	 *          third point of the triangle.
	 * @param loc
	 *          storage vector to save the collision point in (if the ray collides) if null, only boolean is calculated.
	 * @return true if the ray collides.
	 */
	public boolean intersectWhere(Vector3f v0, Vector3f v1, Vector3f v2, Vector3f loc) {
		return intersects(v0, v1, v2, loc, false, false);
	}

	/**
	 * <code>intersects</code> does the actual intersection work.
	 * 
	 * @param v0
	 *          first point of the triangle.
	 * @param v1
	 *          second point of the triangle.
	 * @param v2
	 *          third point of the triangle.
	 * @param store
	 *          storage vector - if null, no intersection is calc'd
	 * @param doPlanar
	 *          true if we are calcing planar results.
	 * @param quad
	 * @return true if ray intersects triangle
	 */
	private boolean intersects(Vector3f v0, Vector3f v1, Vector3f v2, Vector3f store, boolean doPlanar, boolean quad) {
		TempVars vars = TempVars.get();
		Vector3f tempVa = vars.vect1, tempVb = vars.vect2, tempVc = vars.vect3, tempVd = vars.vect4;

		Vector3f diff = origin.subtract(v0, tempVa);
		Vector3f edge1 = v1.subtract(v0, tempVb);
		Vector3f edge2 = v2.subtract(v0, tempVc);
		Vector3f norm = edge1.cross(edge2, tempVd);

		float dirDotNorm = direction.dot(norm);
		float sign;
		if (dirDotNorm > FastMath.FLT_EPSILON) {
			sign = 1;
		} else if (dirDotNorm < -FastMath.FLT_EPSILON) {
			sign = -1f;
			dirDotNorm = -dirDotNorm;
		} else {
			// ray and triangle/quad are parallel
			vars.release();
			return false;
		}

		float dirDotDiffxEdge2 = sign * direction.dot(diff.cross(edge2, edge2));
		if (dirDotDiffxEdge2 >= 0.0f) {
			float dirDotEdge1xDiff = sign * direction.dot(edge1.crossLocal(diff));

			if (dirDotEdge1xDiff >= 0.0f) {
				if (!quad ? dirDotDiffxEdge2 + dirDotEdge1xDiff <= dirDotNorm : dirDotEdge1xDiff <= dirDotNorm) {
					float diffDotNorm = -sign * diff.dot(norm);
					if (diffDotNorm >= 0.0f) {
						// this method always returns
						vars.release();

						// ray intersects triangle
						// if storage vector is null, just return true,
						if (store == null)
							return true;

						// else fill in.
						float inv = 1f / dirDotNorm;
						float t = diffDotNorm * inv;
						if (!doPlanar) {
							store.set(origin).addLocal(direction.x * t, direction.y * t, direction.z * t);
						} else {
							// these weights can be used to determine
							// interpolated values, such as texture coord.
							// eg. texcoord s,t at intersection point:
							// s = w0*s0 + w1*s1 + w2*s2;
							// t = w0*t0 + w1*t1 + w2*t2;
							float w1 = dirDotDiffxEdge2 * inv;
							float w2 = dirDotEdge1xDiff * inv;
							// float w0 = 1.0f - w1 - w2;
							store.set(t, w1, w2);
						}
						return true;
					}
				}
			}
		}
		vars.release();
		return false;
	}

	public float intersects(Vector3f v0, Vector3f v1, Vector3f v2) {
		float edge1X = v1.x - v0.x;
		float edge1Y = v1.y - v0.y;
		float edge1Z = v1.z - v0.z;

		float edge2X = v2.x - v0.x;
		float edge2Y = v2.y - v0.y;
		float edge2Z = v2.z - v0.z;

		float normX = ((edge1Y * edge2Z) - (edge1Z * edge2Y));
		float normY = ((edge1Z * edge2X) - (edge1X * edge2Z));
		float normZ = ((edge1X * edge2Y) - (edge1Y * edge2X));

		float dirDotNorm = direction.x * normX + direction.y * normY + direction.z * normZ;

		float diffX = origin.x - v0.x;
		float diffY = origin.y - v0.y;
		float diffZ = origin.z - v0.z;

		float sign;
		if (dirDotNorm > FastMath.FLT_EPSILON) {
			sign = 1;
		} else if (dirDotNorm < -FastMath.FLT_EPSILON) {
			sign = -1f;
			dirDotNorm = -dirDotNorm;
		} else {
			// ray and triangle/quad are parallel
			return Float.POSITIVE_INFINITY;
		}

		float diffEdge2X = ((diffY * edge2Z) - (diffZ * edge2Y));
		float diffEdge2Y = ((diffZ * edge2X) - (diffX * edge2Z));
		float diffEdge2Z = ((diffX * edge2Y) - (diffY * edge2X));

		float dirDotDiffxEdge2 = sign * (direction.x * diffEdge2X + direction.y * diffEdge2Y + direction.z * diffEdge2Z);

		if (dirDotDiffxEdge2 >= 0.0f) {
			diffEdge2X = ((edge1Y * diffZ) - (edge1Z * diffY));
			diffEdge2Y = ((edge1Z * diffX) - (edge1X * diffZ));
			diffEdge2Z = ((edge1X * diffY) - (edge1Y * diffX));

			float dirDotEdge1xDiff = sign * (direction.x * diffEdge2X + direction.y * diffEdge2Y + direction.z * diffEdge2Z);

			if (dirDotEdge1xDiff >= 0.0f) {
				if (dirDotDiffxEdge2 + dirDotEdge1xDiff <= dirDotNorm) {
					float diffDotNorm = -sign * (diffX * normX + diffY * normY + diffZ * normZ);
					if (diffDotNorm >= 0.0f) {
						// ray intersects triangle
						// fill in.
						float inv = 1f / dirDotNorm;
						float t = diffDotNorm * inv;
						return t;
					}
				}
			}
		}

		return Float.POSITIVE_INFINITY;
	}

	/**
	 * <code>intersectWherePlanar</code> determines if the Ray intersects a quad defined by the specified points and if so
	 * it stores the point of intersection in the given loc vector as t, u, v where t is the distance from the origin to
	 * the point of intersection and u,v is the intersection point in terms of the quad plane. One edge of the quad is
	 * [v0,v1], another one [v0,v2]. The behaviour thus is like
	 * {@link #intersectWherePlanar(Vector3f, Vector3f, Vector3f, Vector3f)} except for the extended area, which is
	 * equivalent to the union of the triangles [v0,v1,v2] and [-v0+v1+v2,v1,v2].
	 * 
	 * @param v0
	 *          top left point of the quad.
	 * @param v1
	 *          top right point of the quad.
	 * @param v2
	 *          bottom left point of the quad.
	 * @param loc
	 *          storage vector to save the collision point in (if the ray collides) as t, u, v
	 * @return true if the ray collides with the quad.
	 */
	public boolean intersectWherePlanarQuad(Vector3f v0, Vector3f v1, Vector3f v2, Vector3f loc) {
		return intersects(v0, v1, v2, loc, true, true);
	}

	@Override
	public int collideWith(Collidable other, CollisionResults results) {
		if (other instanceof BoundingVolume) {
			BoundingVolume bv = (BoundingVolume) other;
			return bv.collideWith(this, results);
		} else {
			throw new UnsupportedCollisionException();
		}
	}

	public float distanceSquared(Vector3f point) {
		TempVars vars = TempVars.get();
		Vector3f tempVa = vars.vect1, tempVb = vars.vect2;

		point.subtract(origin, tempVa);
		float rayParam = direction.dot(tempVa);
		if (rayParam > 0) {
			origin.add(direction.mult(rayParam, tempVb), tempVb);
		} else {
			tempVb.set(origin);
		}

		tempVb.subtract(point, tempVa);
		float len = tempVa.lengthSquared();
		vars.release();
		return len;
	}

	/**
	 * <code>getOrigin</code> retrieves the origin point of the ray.
	 * 
	 * @return the origin of the ray.
	 */
	public Vector3f getOrigin() {
		return origin;
	}

	/**
	 * <code>setOrigin</code> sets the origin of the ray.
	 * 
	 * @param origin
	 *          the origin of the ray.
	 */
	public void setOrigin(Vector3f origin) {
		this.origin.set(origin);
	}

	/**
	 * <code>getLimit</code> returns the limit or the ray, aka the length. If the limit is not infinity, then this ray is
	 * a line with length <code>
	 * limit</code>.
	 * 
	 * @return
	 */
	public float getLimit() {
		return limit;
	}

	/**
	 * <code>setLimit</code> sets the limit of the ray.
	 * 
	 * @param limit
	 *          the limit of the ray.
	 * @see Ray#getLimit()
	 */
	public void setLimit(float limit) {
		this.limit = limit;
	}

	/**
	 * <code>getDirection</code> retrieves the direction vector of the ray.
	 * 
	 * @return the direction of the ray.
	 */
	public Vector3f getDirection() {
		return direction;
	}

	/**
	 * <code>setDirection</code> sets the direction vector of the ray.
	 * 
	 * @param direction
	 *          the direction of the ray.
	 */
	public void setDirection(Vector3f direction) {
		this.direction.set(direction);
	}

	/**
	 * Copies information from a source ray into this ray.
	 * 
	 * @param source
	 *          the ray to copy information from
	 */
	public void set(Ray source) {
		origin.set(source.getOrigin());
		direction.set(source.getDirection());
	}

	@Override
	public String toString() {
		return getClass().getSimpleName() + " [Origin: " + origin + ", Direction: " + direction + "]";
	}

	@Override
	public Ray clone() {
		try {
			Ray r = (Ray) super.clone();
			r.direction = direction.clone();
			r.origin = origin.clone();
			return r;
		} catch (CloneNotSupportedException e) {
			throw new AssertionError();
		}
	}
}

📎 첨부파일

댓글 작성 권한이 없습니다.
🏆 포인트 랭킹 TOP 10
순위 닉네임 포인트
1 no_profile 타키야겐지쪽지보내기 자기소개 아이디로 검색 전체게시물 102,949
2 no_profile 동가리쪽지보내기 자기소개 아이디로 검색 전체게시물 63,733
3 no_profile 라프텔쪽지보내기 자기소개 아이디로 검색 전체게시물 51,771
4 no_profile 불멸의행복쪽지보내기 자기소개 아이디로 검색 전체게시물 36,923
5 서번트쪽지보내기 자기소개 아이디로 검색 전체게시물 35,011
6 no_profile 닥터스쪽지보내기 자기소개 아이디로 검색 전체게시물 29,470
7 no_profile 검은고양이쪽지보내기 자기소개 아이디로 검색 전체게시물 29,077
8 no_profile Revolution쪽지보내기 자기소개 아이디로 검색 전체게시물 28,199
9 no_profile 보거스쪽지보내기 자기소개 아이디로 검색 전체게시물 26,731
10 no_profile 호롤롤로쪽지보내기 자기소개 아이디로 검색 전체게시물 17,020
알림 0