import {FrustumPlaneEnum} from './FrustumPlaneEnum';
import {PlaneSurface} from './PlaneSurface';
//==========================================================
// 空间视截体。
//
// @struct
// @author maocy
// @version 150116
//==========================================================
export class FrustumPlanes {
// 面集合
public PlaneSurfaces: Array;
//============================================================
// 构造处理。
//
// @method
//============================================================
public constructor() {
var PlaneSurfaces = this.PlaneSurfaces = new Array();
for (var i = 0; i < FrustumPlaneEnum.Count; i++) {
PlaneSurfaces.push(new PlaneSurface());
}
}
//============================================================
// 检查点是否在视截体内。
//
// @param x 坐标X
// @param y 坐标Y
// @param z 坐标Z
//============================================================
public containsPoint(x, y, z) {
var PlaneSurfaces = this.PlaneSurfaces;
for (var i = 0; i < FrustumPlaneEnum.Count; i++) {
if (PlaneSurfaces[i].dot(x, y, z) < 0) {
return false;
}
}
return true;
}
//============================================================
// 检查立方体是否在视截体内。
//
// @param centerX 中心点X坐标
// @param centerY 中心点Y坐标
// @param centerZ 中心点Z坐标
// @param size 大小
// @return 是否包含
//============================================================
public containsCube(cx: number, cy: number, cz: number, size: number) {
var PlaneSurfaces = this.PlaneSurfaces;
for (var i = 0; i < FrustumPlaneEnum.Count; i++) {
var p = PlaneSurfaces[i];
if (p.dot(cx - size, cy - size, cz - size) >= 0) {
continue;
}
if (p.dot(cx + size, cy - size, cz - size) >= 0) {
continue;
}
if (p.dot(cx - size, cy + size, cz - size) >= 0) {
continue;
}
if (p.dot(cx + size, cy + size, cz - size) >= 0) {
continue;
}
if (p.dot(cx - size, cy - size, cz + size) >= 0) {
continue;
}
if (p.dot(cx + size, cy - size, cz + size) >= 0) {
continue;
}
if (p.dot(cx - size, cy + size, cz + size) >= 0) {
continue;
}
if (p.dot(cx + size, cy + size, cz + size) >= 0) {
continue;
}
return false;
}
return true;
}
//============================================================
// 检查长方体是否在视截体内。
//
// @param cx:centerX 中心点X坐标
// @param cy:centerY 中心点Y坐标
// @param cz:centerZ 中心点Z坐标
// @param sx:sizeX X大小
// @param sy:sizeY Y大小
// @param sz:sizeZ Z大小
// @return 是否包含
//============================================================
public containsRectangle(cx: number, cy: number, cz: number, sx: number, sy: number, sz: number) {
var PlaneSurfaces = this.PlaneSurfaces;
for (var i = 0; i < FrustumPlaneEnum.Count; i++) {
var p = PlaneSurfaces[i];
if (p.dot(cx - sx, cy - sy, cz - sz) >= 0) {
continue;
}
if (p.dot(cx + sx, cy - sy, cz - sz) >= 0) {
continue;
}
if (p.dot(cx - sx, cy + sy, cz - sz) >= 0) {
continue;
}
if (p.dot(cx + sx, cy + sy, cz - sz) >= 0) {
continue;
}
if (p.dot(cx - sx, cy - sy, cz + sz) >= 0) {
continue;
}
if (p.dot(cx + sx, cy - sy, cz + sz) >= 0) {
continue;
}
if (p.dot(cx - sx, cy + sy, cz + sz) >= 0) {
continue;
}
if (p.dot(cx + sx, cy + sy, cz + sz) >= 0) {
continue;
}
return false;
}
return true;
}
//============================================================
// 检查长方体是否在视截体内。
//
// @param p:corners:Array 顶点集合
// @return 是否包含
//============================================================
public containsCorners(p) {
var PlaneSurfaces = this.PlaneSurfaces;
for (var i = FrustumPlaneEnum.Count - 1; i >= 0; i--) {
var l = PlaneSurfaces[i];
if (l.dot(p[0], p[1], p[2]) >= 0) {
continue;
}
if (l.dot(p[3], p[4], p[5]) >= 0) {
continue;
}
if (l.dot(p[6], p[7], p[8]) >= 0) {
continue;
}
if (l.dot(p[9], p[10], p[11]) >= 0) {
continue;
}
if (l.dot(p[12], p[13], p[14]) >= 0) {
continue;
}
if (l.dot(p[15], p[16], p[17]) >= 0) {
continue;
}
if (l.dot(p[18], p[19], p[20]) >= 0) {
continue;
}
if (l.dot(p[21], p[22], p[23]) >= 0) {
continue;
}
return false;
}
return true;
}
//============================================================
// 检查球体是否在视截体内。
//
// @param px:centerX 中心点X坐标
// @param py:centerY 中心点Y坐标
// @param pz:centerZ 中心点Z坐标
// @param pr:radius 半径
// @return 是否包含
//============================================================
public containsSphere(px: number, py: number, pz: number, pr: number): boolean {
var PlaneSurfaces = this.PlaneSurfaces;
for (var i = 0; i < FrustumPlaneEnum.Count; i++) {
if (PlaneSurfaces[i].dot(px, py, pz) < -pr) {
return false;
}
}
return true;
}
//============================================================
// 更新可视范围信息。
//
// @param p 矩阵数据
//============================================================
public updateVision(p) {
var PlaneSurfaces = this.PlaneSurfaces;
// 计算视截体的近平面
var pn = PlaneSurfaces[FrustumPlaneEnum.Near];
pn.a = p[0 + 3] + p[0 + 2];
pn.b = p[4 + 3] + p[4 + 2];
pn.c = p[8 + 3] + p[8 + 2];
pn.d = p[12 + 3] + p[12 + 2];
pn.normalize();
// 计算视截体的远平面
var pf = PlaneSurfaces[FrustumPlaneEnum.Far];
pf.a = p[0 + 3] - p[0 + 2];
pf.b = p[4 + 3] - p[4 + 2];
pf.c = p[8 + 3] - p[8 + 2];
pf.d = p[12 + 3] - p[12 + 2];
pf.normalize();
// 计算视截体的左平面
var pl = PlaneSurfaces[FrustumPlaneEnum.Left];
pl.a = p[0 + 3] - p[0 + 0];
pl.b = p[4 + 3] - p[4 + 0];
pl.c = p[8 + 3] - p[8 + 0];
pl.d = p[12 + 3] - p[12 + 0];
pl.normalize();
// 计算视截体的右平面
var pr = PlaneSurfaces[FrustumPlaneEnum.Right];
pr.a = p[0 + 3] + p[0 + 0];
pr.b = p[4 + 3] + p[4 + 0];
pr.c = p[8 + 3] + p[8 + 0];
pr.d = p[12 + 3] + p[12 + 0];
pr.normalize();
// 计算视截体的顶平面
var pt = PlaneSurfaces[FrustumPlaneEnum.Top];
pt.a = p[0 + 3] - p[0 + 1];
pt.b = p[4 + 3] - p[4 + 1];
pt.c = p[8 + 3] - p[8 + 1];
pt.d = p[12 + 3] - p[12 + 1];
pt.normalize();
// 计算视截体的底平面
var pb = PlaneSurfaces[FrustumPlaneEnum.Bottom];
pb.a = p[0 + 3] + p[0 + 1];
pb.b = p[4 + 3] + p[4 + 1];
pb.c = p[8 + 3] + p[8 + 1];
pb.d = p[12 + 3] + p[12 + 1];
pb.normalize();
}
}