mirror of
https://github.com/RandomityGuy/MBHaxe.git
synced 2025-12-24 08:52:43 +00:00
316 lines
6.4 KiB
Haxe
316 lines
6.4 KiB
Haxe
package mesh;
|
|
|
|
import h3d.prim.*;
|
|
import h3d.col.Point;
|
|
|
|
class Polygon extends MeshPrimitive {
|
|
public var points:Array<Point>;
|
|
public var normals:Array<Point>;
|
|
public var tangents:Array<Point>;
|
|
public var bitangents:Array<Point>;
|
|
public var texMatNormals:Array<Point>;
|
|
public var uvs:Array<UV>;
|
|
public var idx:hxd.IndexBuffer;
|
|
|
|
var bounds:h3d.col.Bounds;
|
|
|
|
var scaled = 1.;
|
|
var translatedX = 0.;
|
|
var translatedY = 0.;
|
|
var translatedZ = 0.;
|
|
|
|
public function new(points, ?idx) {
|
|
this.points = points;
|
|
this.idx = idx;
|
|
}
|
|
|
|
override function getBounds() {
|
|
if (bounds == null) {
|
|
var b = new h3d.col.Bounds();
|
|
for (p in points)
|
|
b.addPoint(p);
|
|
bounds = b;
|
|
}
|
|
return bounds;
|
|
}
|
|
|
|
override function alloc(engine:h3d.Engine) {
|
|
dispose();
|
|
|
|
var size = 3;
|
|
var names = ["position"];
|
|
var positions = [0];
|
|
if (normals != null) {
|
|
names.push("normal");
|
|
positions.push(size);
|
|
size += 3;
|
|
}
|
|
if (tangents != null) {
|
|
names.push("t");
|
|
positions.push(size);
|
|
size += 3;
|
|
}
|
|
if (bitangents != null) {
|
|
names.push("b");
|
|
positions.push(size);
|
|
size += 3;
|
|
}
|
|
if (texMatNormals != null) {
|
|
names.push("n");
|
|
positions.push(size);
|
|
size += 3;
|
|
}
|
|
if (uvs != null) {
|
|
names.push("uv");
|
|
positions.push(size);
|
|
size += 2;
|
|
}
|
|
|
|
var buf = new hxd.FloatBuffer();
|
|
for (k in 0...points.length) {
|
|
var p = points[k];
|
|
buf.push(p.x);
|
|
buf.push(p.y);
|
|
buf.push(p.z);
|
|
if (normals != null) {
|
|
var n = normals[k];
|
|
buf.push(n.x);
|
|
buf.push(n.y);
|
|
buf.push(n.z);
|
|
}
|
|
if (tangents != null) {
|
|
var t = tangents[k];
|
|
buf.push(t.x);
|
|
buf.push(t.y);
|
|
buf.push(t.z);
|
|
}
|
|
if (bitangents != null) {
|
|
var t = bitangents[k];
|
|
buf.push(t.x);
|
|
buf.push(t.y);
|
|
buf.push(t.z);
|
|
}
|
|
if (texMatNormals != null) {
|
|
var t = texMatNormals[k];
|
|
buf.push(t.x);
|
|
buf.push(t.y);
|
|
buf.push(t.z);
|
|
}
|
|
if (uvs != null) {
|
|
var t = uvs[k];
|
|
buf.push(t.u);
|
|
buf.push(t.v);
|
|
}
|
|
}
|
|
var flags:Array<h3d.Buffer.BufferFlag> = [];
|
|
if (idx == null)
|
|
flags.push(Triangles);
|
|
if (normals == null || tangents != null)
|
|
flags.push(RawFormat);
|
|
buffer = h3d.Buffer.ofFloats(buf, size, flags);
|
|
|
|
for (i in 0...names.length)
|
|
addBuffer(names[i], buffer, positions[i]);
|
|
|
|
if (idx != null)
|
|
indexes = h3d.Indexes.alloc(idx);
|
|
}
|
|
|
|
public function unindex() {
|
|
if (idx != null && points.length != idx.length) {
|
|
var p = [];
|
|
var used = [];
|
|
for (i in 0...idx.length)
|
|
p.push(points[idx[i]].clone());
|
|
if (normals != null) {
|
|
var n = [];
|
|
for (i in 0...idx.length)
|
|
n.push(normals[idx[i]].clone());
|
|
normals = n;
|
|
}
|
|
if (tangents != null) {
|
|
var t = [];
|
|
for (i in 0...idx.length)
|
|
t.push(tangents[idx[i]].clone());
|
|
tangents = t;
|
|
}
|
|
if (uvs != null) {
|
|
var t = [];
|
|
for (i in 0...idx.length)
|
|
t.push(uvs[idx[i]].clone());
|
|
uvs = t;
|
|
}
|
|
points = p;
|
|
idx = null;
|
|
}
|
|
}
|
|
|
|
public function translate(dx, dy, dz) {
|
|
translatedX += dx;
|
|
translatedY += dy;
|
|
translatedZ += dz;
|
|
for (p in points) {
|
|
p.x += dx;
|
|
p.y += dy;
|
|
p.z += dz;
|
|
}
|
|
}
|
|
|
|
public function scale(s:Float) {
|
|
scaled *= s;
|
|
for (p in points) {
|
|
p.x *= s;
|
|
p.y *= s;
|
|
p.z *= s;
|
|
}
|
|
}
|
|
|
|
public function addNormals() {
|
|
// make per-point normal
|
|
normals = new Array();
|
|
for (i in 0...points.length)
|
|
normals[i] = new Point();
|
|
var pos = 0;
|
|
for (i in 0...triCount()) {
|
|
var i0, i1, i2;
|
|
if (idx == null) {
|
|
i0 = pos++;
|
|
i1 = pos++;
|
|
i2 = pos++;
|
|
} else {
|
|
i0 = idx[pos++];
|
|
i1 = idx[pos++];
|
|
i2 = idx[pos++];
|
|
}
|
|
var p0 = points[i0];
|
|
var p1 = points[i1];
|
|
var p2 = points[i2];
|
|
// this is the per-face normal
|
|
var n = p1.sub(p0).cross(p2.sub(p0));
|
|
// add it to each point
|
|
normals[i0].x += n.x;
|
|
normals[i0].y += n.y;
|
|
normals[i0].z += n.z;
|
|
normals[i1].x += n.x;
|
|
normals[i1].y += n.y;
|
|
normals[i1].z += n.z;
|
|
normals[i2].x += n.x;
|
|
normals[i2].y += n.y;
|
|
normals[i2].z += n.z;
|
|
}
|
|
// normalize all normals
|
|
for (n in normals)
|
|
n.normalize();
|
|
}
|
|
|
|
public function addTangents() {
|
|
if (normals == null)
|
|
addNormals();
|
|
if (uvs == null)
|
|
addUVs();
|
|
tangents = [];
|
|
for (i in 0...points.length)
|
|
tangents[i] = new Point();
|
|
var pos = 0;
|
|
for (i in 0...triCount()) {
|
|
var i0, i1, i2;
|
|
if (idx == null) {
|
|
i0 = pos++;
|
|
i1 = pos++;
|
|
i2 = pos++;
|
|
} else {
|
|
i0 = idx[pos++];
|
|
i1 = idx[pos++];
|
|
i2 = idx[pos++];
|
|
}
|
|
var p0 = points[i0];
|
|
var p1 = points[i1];
|
|
var p2 = points[i2];
|
|
var uv0 = uvs[i0];
|
|
var uv1 = uvs[i1];
|
|
var uv2 = uvs[i2];
|
|
var n = normals[i0];
|
|
|
|
var k0 = p1.sub(p0);
|
|
var k1 = p2.sub(p0);
|
|
k0.scale(uv2.v - uv0.v);
|
|
k1.scale(uv1.v - uv0.v);
|
|
var t = k0.sub(k1);
|
|
var b = n.cross(t);
|
|
b.normalize();
|
|
t = b.cross(n);
|
|
t.normalize();
|
|
|
|
// add it to each point
|
|
tangents[i0].x += t.x;
|
|
tangents[i0].y += t.y;
|
|
tangents[i0].z += t.z;
|
|
tangents[i1].x += t.x;
|
|
tangents[i1].y += t.y;
|
|
tangents[i1].z += t.z;
|
|
tangents[i2].x += t.x;
|
|
tangents[i2].y += t.y;
|
|
tangents[i2].z += t.z;
|
|
}
|
|
for (t in tangents)
|
|
t.normalize();
|
|
}
|
|
|
|
public function addUVs() {
|
|
uvs = [];
|
|
for (i in 0...points.length)
|
|
uvs[i] = new UV(points[i].x, points[i].y);
|
|
}
|
|
|
|
public function uvScale(su:Float, sv:Float) {
|
|
if (uvs == null)
|
|
throw "Missing UVs";
|
|
var m = new Map<UV, Bool>();
|
|
for (t in uvs) {
|
|
if (m.exists(t))
|
|
continue;
|
|
m.set(t, true);
|
|
t.u *= su;
|
|
t.v *= sv;
|
|
}
|
|
}
|
|
|
|
override function triCount() {
|
|
var n = super.triCount();
|
|
if (n != 0)
|
|
return n;
|
|
return Std.int((idx == null ? points.length : idx.length) / 3);
|
|
}
|
|
|
|
override function vertexCount() {
|
|
return points.length;
|
|
}
|
|
|
|
override function getCollider():h3d.col.Collider {
|
|
var vertexes = new haxe.ds.Vector<hxd.impl.Float32>(points.length * 3);
|
|
var indexes = new haxe.ds.Vector<Int>(idx.length);
|
|
var vid = 0;
|
|
for (p in points) {
|
|
vertexes[vid++] = p.x;
|
|
vertexes[vid++] = p.y;
|
|
vertexes[vid++] = p.z;
|
|
}
|
|
for (i in 0...idx.length)
|
|
indexes[i] = idx[i];
|
|
var poly = new h3d.col.Polygon();
|
|
poly.addBuffers(vertexes, indexes);
|
|
return poly;
|
|
}
|
|
|
|
override function render(engine:h3d.Engine) {
|
|
if (buffer == null || buffer.isDisposed())
|
|
alloc(engine);
|
|
var bufs = getBuffers(engine);
|
|
if (indexes != null)
|
|
engine.renderMultiBuffers(bufs, indexes);
|
|
else if (buffer.flags.has(Quads))
|
|
engine.renderMultiBuffers(bufs, engine.mem.quadIndexes, 0, triCount());
|
|
else
|
|
engine.renderMultiBuffers(bufs, engine.mem.triIndexes, 0, triCount());
|
|
}
|
|
}
|