Browse Source

Util完成

master
blobt 3 years ago
parent
commit
c355ebe409
  1. 6
      src/render/common.ts
  2. 128
      src/render/core/Primitives.ts
  3. 385
      src/render/math/Util.ts

6
src/render/common.ts

@ -31,3 +31,9 @@ export enum EGLTexWrapType {
GL_MIRRORED_REPEAT, GL_MIRRORED_REPEAT,
GL_CLAMP_TO_EDGE GL_CLAMP_TO_EDGE
} }
export enum EPlaneLoc {
FRONT, // 在平面的正面
BACK, // 在平面的背面
COPLANAR // 与平面共面
}

128
src/render/core/Primitives.ts

@ -0,0 +1,128 @@
import { vec2, vec3, vec4, mat4 } from "../math";
import { GLAttribBits, GLAttribState } from "../webgl/WebGLAttribState";
import { GLStaticMesh } from "../webgl/WebGLMesh";
export class GeometryData {
/**
* @var
*/
public positions: vec3[] = [];
/**
* @var uv坐标
*/
public uvs: vec2[] = [];
/**
* @var 线
*/
public normals: vec3[] = [];
/**
* @var
*/
public colors: vec4[] = [];
/**
* @var 线
*/
public tangents: vec4[] = [];
/**
* @var
*/
public indices: number[] = [];
/**
* attrib bit
* @returns
*/
public getAttribBits(): GLAttribBits {
if (this.positions.length === 0) {
throw new Error("position data is required");
}
let ret: GLAttribBits = GLAttribState.POSITION_BIT;
if (this.uvs.length > 0) {
ret |= GLAttribState.TEXCOORD_BIT;
}
if (this.normals.length > 0) {
ret |= GLAttribState.NORMAL_BIT;
}
if (this.colors.length > 0) {
ret |= GLAttribState.COLOR_BIT;
}
if (this.tangents.length > 0) {
ret |= GLAttribState.TANGENT_BIT;
}
return ret;
}
public makeStaticVAO(gl: WebGLRenderingContext, needNormal: boolean = false, needUV: boolean = true): GLStaticMesh {
let bits: GLAttribBits = this.getAttribBits();
if (needNormal === false) {
bits &= ~GLAttribState.NORMAL_BIT;
}
if (needUV === false) {
bits &= ~GLAttribState.TEXCOORD_BIT;
}
let stride: number = GLAttribState.getVertexBytesStride(bits);
let step: number = stride / Float32Array.BYTES_PER_ELEMENT;
let arrayBuffer: ArrayBuffer = new ArrayBuffer(stride * this.positions.length);
let buffer: Float32Array = new Float32Array(arrayBuffer);
for (let i: number = 0; i < this.positions.length; i++) {
let j: number = i * step;
let idx: number = 0;
//位置
buffer[j + (idx++)] = this.positions[i].x;
buffer[j + (idx++)] = this.positions[i].y;
buffer[j + (idx++)] = this.positions[i].z;
//法线
if (bits & GLAttribState.NORMAL_BIT) {
buffer[j + (idx++)] = this.normals[i].x;
buffer[j + (idx++)] = this.normals[i].y;
buffer[j + (idx++)] = this.normals[i].z;
}
//纹理
if (bits & GLAttribState.TEXCOORD_BIT) {
buffer[j + (idx++)] = this.uvs[i].x;
buffer[j + (idx++)] = this.uvs[i].y;
}
//颜色
if (bits & GLAttribState.COLOR_BIT) {
buffer[j + (idx++)] = this.colors[i].x;
buffer[j + (idx++)] = this.colors[i].y;
buffer[j + (idx++)] = this.colors[i].z;
buffer[j + (idx++)] = this.colors[i].w;
}
//切线
if (bits & GLAttribState.TANGENT_BIT) {
buffer[j + (idx++)] = this.tangents[i].x;
buffer[j + (idx++)] = this.tangents[i].y;
buffer[j + (idx++)] = this.tangents[i].z;
buffer[j + (idx++)] = this.tangents[i].w;
}
}
let mesh: GLStaticMesh = new GLStaticMesh(gl, bits, buffer, this.indices.length > 0 ? new Uint16Array(this.indices) : null);
return mesh;
}
}

385
src/render/math/Util.ts

@ -1,3 +1,7 @@
import { EPSILON, EPlaneLoc } from "../common";
import { vec2, vec3, vec4, mat4 } from ".";
import { quat } from "./Quat";
export class Util { export class Util {
/** /**
* x是否是2的n次方x是不是1248163264..... * x是否是2的n次方x是不是1248163264.....
@ -26,4 +30,385 @@ export class Util {
} }
return x + 1; return x + 1;
} }
/**
* /
* @param degree
* @returns
*/
public static toRadian(degree: number): number {
return degree * Math.PI / 180;
}
/**
*
* @param left
* @param right
* @returns
*/
public static numberEuaqls(left: number, right: number): boolean {
if (Math.abs(left - right) > EPSILON) {
return false;
}
return true;
}
/**
*
* @param x
* @param min
* @param max
* @returns
*/
public static clamp(x: number, min: number, max: number): number {
return (x < min) ? min : (x > max) ? max : x;
}
/**
*
* @param localPt
* @param mvp
* @param viewport
* @param viewportPt
* @returns
*/
public static obj2GLViewportSpace(localPt: vec3, mvp: mat4, viewport: Int32Array | Float32Array, viewportPt: vec3): boolean {
let v: vec4 = new vec4([localPt.x, localPt.y, localPt.z, 1.0]);
//这里相当于 v = mvp * v, 将顶点从local坐标系变换到投影坐标系
mvp.multiplyVec4(v, v);
//如果变换后的w为0,则返回false
if (v.w === 0.0) {
return false;
}
// 将裁剪坐标系的点的x / y / z分量除以w,得到normalized坐标值[ -1 , 1 ]之间
v.x /= v.w;
v.y /= v.w;
v.z /= v.w;
// [-1 , 1]标示的点变换到视口坐标系
v.x = v.x * 0.5 + 0.5;
v.y = v.y * 0.5 + 0.5;
v.z = v.z * 0.5 + 0.5;
// 视口坐标系再变换到屏幕坐标系
viewportPt.x = v.x * viewport[2] + viewport[0];
viewportPt.y = v.y * viewport[3] + viewport[1];
viewportPt.z = v.z;
return true;
}
/**
* 3
* @param a
* @param b
* @param c
* @param result
* @returns
*/
public static computeNormal(a: vec3, b: vec3, c: vec3, result: vec3 | null): vec3 {
if (!result) {
result = new vec3();
}
let l0: vec3 = new vec3();
let l1: vec3 = new vec3();
vec3.difference(b, a, l0);
vec3.difference(c, a, l1);
vec3.cross(l0, l1, result);
result.normalize();
return result;
}
/**
* 3
* @param a
* @param b
* @param c
* @param result
* @returns
*/
public static planeFromPoints(a: vec3, b: vec3, c: vec3, result: vec4 | null = null): vec4 {
if (!result) {
result = new vec4();
}
let normal: vec3 = new vec3();
Util.computeNormal(a, b, c, normal);
let d: number = -vec3.dot(normal, a);
result.x = normal.x;
result.y = normal.y;
result.z = normal.z;
result.w = d;
return result;
}
/**
* 线
* @param p
* @param normal
* @param result
* @returns
*/
public static planeFromPointNormal(p: vec3, normal: vec3, result: vec4 | null = null): vec4 {
if (!result) {
result = new vec4();
}
let d: number = -vec3.dot(normal, p);
result.x = normal.x;
result.y = normal.y;
result.z = normal.z;
result.w = d;
return result;
}
/**
*
* @param polygon
* @returns
*/
public static planeFromPolygon(polygon: vec3[]): vec4 {
if (polygon.length < 3) {
throw new Error("The number of vertices of polygon must be greater than or equal to 3 ");
}
return Util.planeFromPoints(polygon[0], polygon[1], polygon[2]);
}
/**
*
* @param plane
* @param point
* @returns
*/
public static planeDistanceFromPoint(plane: vec4, point: vec3): number {
return (point.x * plane.x + point.y * plane.y + point.z * plane.z + plane.w);
}
/**
*
* @param plane
* @param point
* @returns
*/
public static planeTestPoint(plane: vec4, point: vec3): EPlaneLoc {
let num: number = Util.planeDistanceFromPoint(plane, point);
if (num > EPSILON) {
return EPlaneLoc.FRONT;
} else if (num < - EPSILON) {
return EPlaneLoc.BACK;
} else {
return EPlaneLoc.COPLANAR;
}
}
/**
*
* @param plane
* @returns
*/
public static planeNormalize(plane: vec4): number {
let length: number;
length = Math.sqrt(plane.x * plane.x + plane.y * plane.y + plane.z * plane.z);
if (length === 0) {
throw new Error("The plane area is 0");
}
plane.x /= length;
plane.y /= length;
plane.z /= length;
plane.w /= length;
return length;
}
/**
*
* @param v
* @param mins
* @param maxs
*/
public static boundBoxAddPoint(v: vec3, mins: vec3, maxs: vec3): void {
if (v.x < mins.x) {
mins.x = v.x;
}
if (v.x > maxs.x) {
maxs.x = v.x;
}
if (v.y < mins.y) {
mins.y = v.y;
}
if (v.y > maxs.y) {
maxs.y = v.y;
}
if (v.z < mins.z) {
mins.z = v.z;
}
if (v.z > maxs.z) {
maxs.z = v.z;
}
}
/**
*
* @param mins
* @param maxs
* @param value
*/
public static boundBoxClear(mins: vec3, maxs: vec3, value: number = Infinity): void {
mins.x = mins.y = mins.z = value; // 初始化时,让mins表示浮点数的最大范围
maxs.x = maxs.y = maxs.z = -value; // 初始化是,让maxs表示浮点数的最小范围
}
/**
*
* @param mins
* @param maxs
* @param out
* @returns
*/
public static boundBoxGetCenter(mins: vec3, maxs: vec3, out: vec3 | null = null): vec3 {
if (out === null) {
out = new vec3();
}
//(maxs + mins) * 0.5
vec3.sum(mins, maxs, out);
out.scale(0.5);
return out;
}
/**
* 8
* @param mins
* @param maxs
* @param pts8
* /3--------/7 |
* / | / |
* / | / |
* 1---------5 |
* | /2- - -|- -6
* | / | /
* |/ | /
* 0---------4/
*/
public static boundBoxGet8Points(mins: vec3, maxs: vec3, pts8: vec3[]): void {
//获取中心点
let center: vec3 = Util.boundBoxGetCenter(mins, maxs);
//获取最大点到中心点之间的距离向量
let maxs2center: vec3 = vec3.difference(center, maxs);
pts8.push(new vec3([center.x + maxs2center.x, center.y + maxs2center.y, center.z + maxs2center.z])); // 0
pts8.push(new vec3([center.x + maxs2center.x, center.y - maxs2center.y, center.z + maxs2center.z])); // 1
pts8.push(new vec3([center.x + maxs2center.x, center.y + maxs2center.y, center.z - maxs2center.z])); // 2
pts8.push(new vec3([center.x + maxs2center.x, center.y - maxs2center.y, center.z - maxs2center.z])); // 3
pts8.push(new vec3([center.x - maxs2center.x, center.y + maxs2center.y, center.z + maxs2center.z])); // 4
pts8.push(new vec3([center.x - maxs2center.x, center.y - maxs2center.y, center.z + maxs2center.z])); // 5
pts8.push(new vec3([center.x - maxs2center.x, center.y + maxs2center.y, center.z - maxs2center.z])); // 6
pts8.push(new vec3([center.x - maxs2center.x, center.y - maxs2center.y, center.z - maxs2center.z])); // 7
}
/**
*
* @param mat
* @param mins
* @param maxs
*/
public static boundBoxTransform(mat: mat4, mins: vec3, maxs: vec3): void {
// 获得局部坐标系表示的AABB的8个顶点坐标
let pts: vec3[] = [];
Util.boundBoxGet8Points(mins, maxs, pts);
//变换后的顶点
let out: vec3 = new vec3();
for (let i: number = 0; i < pts.length; i++) {
// 将局部坐标表示的顶点变换到mat坐标空间中去,变换后的结果放在out变量中
mat.multiplyVec3(pts[i], out);
Util.boundBoxAddPoint(out, mins, maxs);
}
}
/**
*
* @param point
* @param mins
* @param maxs
*/
public static boundBoxContainPoint(point: vec3, mins: vec3, maxs: vec3): boolean {
return (point.x >= mins.x && point.x <= maxs.x && point.y >= mins.y && point.y <= maxs.y && point.z >= mins.z && point.z <= maxs.z);
}
/**
*
* @param min1 1 2
* @param max1
* @param min2
* @param max2
* @returns
*/
public static boundBoxBoundBoxOverlap(min1: vec3, max1: vec3, min2: vec3, max2: vec3): boolean {
if (min1.x > max2.x) return false;
if (max1.x < min2.x) return false;
if (min1.y > max2.y) return false;
if (max1.y < min2.y) return false;
if (min1.z > max2.z) return false;
if (max1.z < min2.z) return false;
return true;
}
/**
* y轴 z轴
* @param v
* @param scale
*/
public static convertVec3IDCoord2GLCoord(v: vec3, scale: number = 10.0): void {
let f: number = v.y;
v.y = v.z;
v.z = -f;
if (!Util.numberEuaqls(scale, 0) && !Util.numberEuaqls(scale, 1.0)) {
v.x /= scale;
v.y /= scale;
v.z /= scale;
}
}
/**
*
* @param v
*/
public static convertVec2IDCoord2GLCoord(v: vec2): void {
v.y = 1.0 - v.y;
}
/**
*
* @param pos
* @param q
* @param dest
* @returns
*/
public static matrixFrom(pos: vec3, q: quat, dest: mat4 | null = null): mat4 {
if (dest === null) {
dest = new mat4();
}
q.toMat4(dest);
dest.values[12] = pos.x;
dest.values[13] = pos.y;
dest.values[14] = pos.z;
return dest;
}
} }
Loading…
Cancel
Save