awayjs-display
Version:
AwayJS displaylist classes
1,033 lines (814 loc) • 27.4 kB
text/typescript
import AttributesBuffer from "awayjs-core/lib/attributes/AttributesBuffer";
import AttributesView from "awayjs-core/lib/attributes/AttributesView";
import Short2Attributes from "awayjs-core/lib/attributes/Short2Attributes";
import Short3Attributes from "awayjs-core/lib/attributes/Short3Attributes";
import Float3Attributes from "awayjs-core/lib/attributes/Float3Attributes";
import Float4Attributes from "awayjs-core/lib/attributes/Float4Attributes";
import Byte4Attributes from "awayjs-core/lib/attributes/Byte4Attributes";
import Matrix3D from "awayjs-core/lib/geom/Matrix3D";
import Vector3D from "awayjs-core/lib/geom/Vector3D";
import Box from "awayjs-core/lib/geom/Box";
import Sphere from "awayjs-core/lib/geom/Sphere";
import TriangleElements from "../graphics/TriangleElements";
class ElementsUtils
{
private static tempFloat32x4:Float32Array = new Float32Array(4);
private static LIMIT_VERTS:number = 0xffff;
private static LIMIT_INDICES:number = 0xffffff;
private static _indexSwap:Array<number> = new Array<number>();
public static generateFaceNormals(indexAttributes:Short3Attributes, positionAttributes:AttributesView, output:Float4Attributes, count:number, offset:number = 0):Float4Attributes
{
var indices:Uint16Array = indexAttributes.get(count, offset);
var positions:ArrayBufferView = positionAttributes.get(positionAttributes.count);
if (output == null)
output = new Float4Attributes(count + offset);
else if (output.count < count + offset)
output.count = count + offset;
var indexDim:number = indexAttributes.dimensions;
var positionDim:number = positionAttributes.dimensions;
var faceNormals:Float32Array = output.get(count, offset);
//multiply by dimension to get index length
count *= indexDim;
var i:number = 0;
var j:number = 0;
var index:number;
var x1:number, x2:number, x3:number;
var y1:number, y2:number, y3:number;
var z1:number, z2:number, z3:number;
var dx1:number, dy1:number, dz1:number;
var dx2:number, dy2:number, dz2:number;
var cx:number, cy:number, cz:number;
var d:number;
if (positionDim == 3) {
while (i < count) {
index = indices[i++]*3;
x1 = positions[index];
y1 = positions[index + 1];
z1 = positions[index + 2];
index = indices[i++]*3;
x2 = positions[index];
y2 = positions[index + 1];
z2 = positions[index + 2];
index = indices[i++]*3;
x3 = positions[index];
y3 = positions[index + 1];
z3 = positions[index + 2];
dx1 = x3 - x1;
dy1 = y3 - y1;
dz1 = z3 - z1;
dx2 = x2 - x1;
dy2 = y2 - y1;
dz2 = z2 - z1;
cx = dz1*dy2 - dy1*dz2;
cy = dx1*dz2 - dz1*dx2;
cz = dy1*dx2 - dx1*dy2;
d = Math.sqrt(cx*cx + cy*cy + cz*cz);
// length of cross product = 2*triangle area
faceNormals[j++] = cx;
faceNormals[j++] = cy;
faceNormals[j++] = cz;
faceNormals[j++] = d;
}
} else if (positionDim == 2) {
while (i < count) {
faceNormals[j++] = 0;
faceNormals[j++] = 0;
faceNormals[j++] = 1;
faceNormals[j++] = 1;
i += 3;
}
}
output.set(faceNormals, offset);
return output;
}
public static generateNormals(indexAttributes:Short3Attributes, faceNormalAttributes:Float4Attributes, output:Float3Attributes, concatenatedBuffer:AttributesBuffer):Float3Attributes
{
var indices:Uint16Array = indexAttributes.get(indexAttributes.count);
var faceNormals:Float32Array = faceNormalAttributes.get(faceNormalAttributes.count);
if (output == null)
output = new Float3Attributes(concatenatedBuffer);
var indexDim:number = indexAttributes.dimensions;
var outputDim:number = output.dimensions;
var normals:Float32Array = output.get(output.count);
var i:number = 0;
var len:number = output.count*outputDim;
//clear normal values
while (i < len) {
normals[i++] = 0;
normals[i++] = 0;
normals[i++] = 0;
}
i = 0;
len = indexAttributes.count*indexDim;
var index:number;
var f1:number = 0;
var f2:number = 1;
var f3:number = 2;
//collect face normals
while (i < len) {
index = indices[i++]*outputDim;
normals[index] += faceNormals[f1];
normals[index + 1] += faceNormals[f2];
normals[index + 2] += faceNormals[f3];
index = indices[i++]*outputDim;
normals[index] += faceNormals[f1];
normals[index + 1] += faceNormals[f2];
normals[index + 2] += faceNormals[f3];
index = indices[i++]*outputDim;
normals[index] += faceNormals[f1];
normals[index + 1] += faceNormals[f2];
normals[index + 2] += faceNormals[f3];
f1 += 4;
f2 += 4;
f3 += 4;
}
i = 0;
len = output.count*outputDim;
var vx:number;
var vy:number;
var vz:number;
var d:number;
//normalise normals collections
while (i < len) {
vx = normals[i];
vy = normals[i + 1];
vz = normals[i + 2];
d = 1.0/Math.sqrt(vx*vx + vy*vy + vz*vz);
normals[i++] = vx*d;
normals[i++] = vy*d;
normals[i++] = vz*d;
}
output.set(normals);
return output;
}
public static generateFaceTangents(indexAttributes:Short3Attributes, positionAttributes:AttributesView, uvAttributes:AttributesView, output:Float4Attributes, count:number, offset:number = 0, useFaceWeights:boolean = false):Float4Attributes
{
var indices:Uint16Array = indexAttributes.get(count, offset);
var positions:ArrayBufferView = positionAttributes.get(positionAttributes.count);
var uvs:Float32Array = <Float32Array> uvAttributes.get(uvAttributes.count);
if (output == null)
output = new Float3Attributes(count + offset);
else if (output.count < count + offset)
output.count = count + offset;
var positionDim:number = positionAttributes.dimensions;
var uvDim:number = uvAttributes.dimensions;
var indexDim:number = indexAttributes.dimensions;
var faceTangents:Float32Array = output.get(count, offset);
var i:number = 0;
var index1:number;
var index2:number;
var index3:number;
var v0:number;
var v1:number;
var v2:number;
var dv1:number;
var dv2:number;
var denom:number;
var x0:number, y0:number, z0:number;
var dx1:number, dy1:number, dz1:number;
var dx2:number, dy2:number, dz2:number;
var cx:number, cy:number, cz:number;
//multiply by dimension to get index length
count *= indexDim;
while (i < count) {
index1 = indices[i];
index2 = indices[i + 1];
index3 = indices[i + 2];
v0 = uvs[index1*uvDim + 1];
dv1 = uvs[index2*uvDim + 1] - v0;
dv2 = uvs[index3*uvDim + 1] - v0;
v0 = index1*positionDim;
v1 = index2*positionDim;
v2 = index3*positionDim;
x0 = positions[v0];
dx1 = positions[v1] - x0;
dx2 = positions[v2] - x0;
cx = dv2*dx1 - dv1*dx2;
y0 = positions[v0 + 1];
dy1 = positions[v1 + 1] - y0;
dy2 = positions[v2 + 1] - y0;
cy = dv2*dy1 - dv1*dy2;
if (positionDim == 3) {
z0 = positions[v0 + 2];
dz1 = positions[v1 + 2] - z0;
dz2 = positions[v2 + 2] - z0;
cz = dv2*dz1 - dv1*dz2;
} else {
cz = 0;
}
denom = 1/Math.sqrt(cx*cx + cy*cy + cz*cz);
faceTangents[i++] = denom*cx;
faceTangents[i++] = denom*cy;
faceTangents[i++] = denom*cz;
}
output.set(faceTangents, offset);
return output;
}
public static generateTangents(indexAttributes:Short3Attributes, faceTangentAttributes:Float3Attributes, faceNormalAttributes:Float4Attributes, output:Float3Attributes, concatenatedBuffer:AttributesBuffer):Float3Attributes
{
var indices:Uint16Array = indexAttributes.get(indexAttributes.count);
var faceTangents:Float32Array = faceTangentAttributes.get(faceTangentAttributes.count);
var faceNormals:Float32Array = faceNormalAttributes.get(faceNormalAttributes.count);
if (output == null)
output = new Float3Attributes(concatenatedBuffer);
var indexDim:number = indexAttributes.dimensions;
var outputDim:number = output.dimensions;
var tangents:Float32Array = output.get(output.count);
var i:number = 0;
var len:number = output.count*outputDim;
//clear tangent values
while (i < len) {
tangents[i++] = 0;
tangents[i++] = 0;
tangents[i++] = 0;
}
var weight:number;
var index:number;
var f1:number = 0;
var f2:number = 1;
var f3:number = 2;
var f4:number = 3;
i = 0;
len = indexAttributes.count*indexDim;
//collect face tangents
while (i < len) {
weight = faceNormals[f4];
index = indices[i++]*outputDim;
tangents[index++] += faceTangents[f1]*weight;
tangents[index++] += faceTangents[f2]*weight;
tangents[index] += faceTangents[f3]*weight;
index = indices[i++]*outputDim;
tangents[index++] += faceTangents[f1]*weight;
tangents[index++] += faceTangents[f2]*weight;
tangents[index] += faceTangents[f3]*weight;
index = indices[i++]*outputDim;
tangents[index++] += faceTangents[f1]*weight;
tangents[index++] += faceTangents[f2]*weight;
tangents[index] += faceTangents[f3]*weight;
f1 += 3;
f2 += 3;
f3 += 3;
f4 += 4;
}
i = 0;
len = output.count*outputDim;
var vx:number;
var vy:number;
var vz:number;
var d:number;
//normalise tangents collections
while (i < len) {
vx = tangents[i];
vy = tangents[i + 1];
vz = tangents[i + 2];
d = 1.0/Math.sqrt(vx*vx + vy*vy + vz*vz);
tangents[i++] = vx*d;
tangents[i++] = vy*d;
tangents[i++] = vz*d;
}
output.set(tangents);
return output;
}
public static generateColors(indexAttributes:Short3Attributes, output:Byte4Attributes, concatenatedBuffer:AttributesBuffer, count:number, offset:number = 0):Byte4Attributes
{
if (output == null)
output = new Byte4Attributes(concatenatedBuffer);
var index:number = 0;
var colors:Uint8Array = new Uint8Array(count*4);
while (index < count*4) {
if (index/4 & 1) {
colors[index] = 0xFF;
colors[index + 1] = 0xFF;
colors[index + 2] = 0xFF;
colors[index + 3] = 0xFF;
} else {
colors[index] = 0xFF;
colors[index + 1] = 0xFF;
colors[index + 2] = 0xFF;
colors[index + 3] = 0xFF;
}
index += 4;
}
output.set(colors, offset);
return output;
}
public static scaleUVs(scaleU:number, scaleV:number, output:AttributesView, count:number, offset:number = 0)
{
if (output.count < count + offset)
output.count = count + offset;
var outputDim:number = output.dimensions;
var uvs:ArrayBufferView = output.get(count, offset);
var i:number = 0;
var j:number = 0;
var len:number = count*outputDim;
while (i < len) {
uvs[i++] *= scaleU;
uvs[i++] *= scaleV;
}
output.set(uvs, offset);
}
public static scale(scale:number, output:AttributesView, count:number, offset:number = 0)
{
if (output.count < count + offset)
output.count = count + offset;
var outputDim:number = output.dimensions;
var positions:ArrayBufferView = output.get(count, offset);
var i:number = 0;
var j:number = 0;
var len:number = count*outputDim;
while (i < len) {
positions[i++] *= scale;
positions[i++] *= scale;
positions[i++] *= scale;
}
output.set(positions, offset);
}
public static applyTransformation(transform:Matrix3D, positionAttributes:AttributesView, normalAttributes:Float3Attributes, tangentAttributes:Float3Attributes, count:number, offset:number = 0)
{
//todo: make this compatible with 2-dimensional positions
var positions:ArrayBufferView = positionAttributes.get(count, offset);
var positionDim:number = positionAttributes.dimensions;
var normals:Float32Array;
var normalDim:number;
if (normalAttributes) {
normals = normalAttributes.get(count, offset);
normalDim = normalAttributes.dimensions;
}
var tangents:Float32Array;
var tangentDim:number;
if (tangentAttributes) {
tangents = tangentAttributes.get(count, offset);
tangentDim = tangentAttributes.dimensions;
}
var i:number;
var i1:number;
var i2:number;
var vector:Vector3D = new Vector3D();
var invTranspose:Matrix3D;
if (normalAttributes || tangentAttributes) {
invTranspose = transform.clone();
invTranspose.invert();
invTranspose.transpose();
}
var vi0:number = 0;
var ni0:number = 0;
var ti0:number = 0;
for (i = 0; i < count; ++i) {
// bake position
i1 = vi0 + 1;
i2 = vi0 + 2;
vector.x = positions[vi0];
vector.y = positions[i1];
vector.z = positions[i2];
vector = transform.transformVector(vector);
positions[vi0] = vector.x;
positions[i1] = vector.y;
positions[i2] = vector.z;
vi0 += positionDim;
if (normals) {
// bake normal
i1 = ni0 + 1;
i2 = ni0 + 2;
vector.x = normals[ni0];
vector.y = normals[i1];
vector.z = normals[i2];
vector = invTranspose.deltaTransformVector(vector);
vector.normalize();
normals[ni0] = vector.x;
normals[i1] = vector.y;
normals[i2] = vector.z;
ni0 += normalDim;
}
if (tangents) {
// bake tangent
i1 = ti0 + 1;
i2 = ti0 + 2;
vector.x = tangents[ti0];
vector.y = tangents[i1];
vector.z = tangents[i2];
vector = invTranspose.deltaTransformVector(vector);
vector.normalize();
tangents[ti0] = vector.x;
tangents[i1] = vector.y;
tangents[i2] = vector.z;
ti0 += tangentDim;
}
}
positionAttributes.set(positions, offset);
if (normalAttributes)
normalAttributes.set(normals, offset);
if (tangentAttributes)
tangentAttributes.set(tangents, offset);
}
public static getSubIndices(indexAttributes:Short2Attributes, numVertices:number, indexMappings:Array<number>, indexOffset?:number):AttributesBuffer;
public static getSubIndices(indexAttributes:Short3Attributes, numVertices:number, indexMappings:Array<number>, indexOffset?:number):AttributesBuffer;
public static getSubIndices(indexAttributes:AttributesView, numVertices:number, indexMappings:Array<number>, indexOffset:number = 0):AttributesBuffer
{
var buffer:AttributesBuffer = indexAttributes.buffer;
var numIndices:number = indexAttributes.length;
//reset mappings
indexMappings.length = 0;
//shortcut for those buffers that fit into the maximum buffer sizes
if (numIndices < ElementsUtils.LIMIT_INDICES && numVertices < ElementsUtils.LIMIT_VERTS)
return buffer;
var i:number;
var indices:Uint16Array = <Uint16Array> indexAttributes.get(indexAttributes.count, indexOffset);
var splitIndices:Array<number> = new Array<number>();
var indexSwap:Array<number> = ElementsUtils._indexSwap;
indexSwap.length = numIndices;
for (i = 0; i < numIndices; i++)
indexSwap[i] = -1;
var originalIndex:number;
var splitIndex:number;
var index:number = 0;
var offsetLength:number = indexOffset*indexAttributes.dimensions;
// Loop over all triangles
i = 0;
while (i < numIndices + offsetLength && i + 1 < ElementsUtils.LIMIT_INDICES && index + 1 < ElementsUtils.LIMIT_VERTS) {
originalIndex = indices[i];
if (indexSwap[originalIndex] >= 0) {
splitIndex = indexSwap[originalIndex];
} else {
// This vertex does not yet exist in the split list and
// needs to be copied from the long list.
splitIndex = index++;
indexSwap[originalIndex] = splitIndex;
indexMappings[splitIndex] = originalIndex;
}
// Store new index, which may have come from the swap look-up,
// or from copying a new set of vertex data from the original vector
splitIndices[i++] = splitIndex;
}
buffer = new AttributesBuffer(indexAttributes.size*indexAttributes.dimensions, splitIndices.length/indexAttributes.dimensions);
indexAttributes = indexAttributes.clone(buffer);
indexAttributes.set(splitIndices);
return buffer;
}
public static getSubVertices(vertexBuffer:AttributesBuffer, indexMappings:Array<number>):AttributesBuffer
{
if (!indexMappings.length)
return vertexBuffer;
var stride:number = vertexBuffer.stride;
var vertices:Uint8Array = vertexBuffer.bufferView;
var splitVerts:Uint8Array = new Uint8Array(indexMappings.length*stride);
var splitIndex:number;
var originalIndex:number;
var i:number = 0;
var j:number = 0;
var len:number = indexMappings.length;
for (i = 0; i < len; i++) {
splitIndex = i*stride;
originalIndex = indexMappings[i]*stride;
for (j = 0; j < stride; j++)
splitVerts[splitIndex + j] = vertices[originalIndex + j];
}
vertexBuffer = new AttributesBuffer(stride, len);
vertexBuffer.bufferView = splitVerts;
return vertexBuffer;
}
//TODO - generate this dyanamically based on num tris
public static hitTestTriangleElements(x:number, y:number, z:number, boundingBox:Box, triangleElements:TriangleElements):boolean
{
var positionAttributes:AttributesView = triangleElements.positions;
var curveAttributes:AttributesView = triangleElements.getCustomAtributes("curves");
var count:number = triangleElements.numVertices;
var posDim:number = positionAttributes.dimensions;
var curveDim:number = curveAttributes.dimensions;
var positions:ArrayBufferView = positionAttributes.get(count);
var curves:ArrayBufferView = curveAttributes? curveAttributes.get(count) : null;
var id0:number;
var id1:number;
var id2:number;
var ax:number;
var ay:number;
var bx:number;
var by:number;
var cx:number;
var cy:number;
var index:number = triangleElements.lastCollisionIndex;
if(index != -1 && index < count)
{
precheck:
{
id0 = index + 2;
id1 = index + 1;
id2 = index + 0;
ax = positions[id0 * posDim];
ay = positions[id0 * posDim + 1];
bx = positions[id1 * posDim];
by = positions[id1 * posDim + 1];
cx = positions[id2 * posDim];
cy = positions[id2 * posDim + 1];
//console.log(ax, ay, bx, by, cx, cy);
//from a to p
var dx:number = ax - x;
var dy:number = ay - y;
//edge normal (a-b)
var nx:number = by - ay;
var ny:number = -(bx - ax);
//console.log(ax,ay,bx,by,cx,cy);
var dot:number = (dx * nx) + (dy * ny);
if (dot > 0)
break precheck;
dx = bx - x;
dy = by - y;
nx = cy - by;
ny = -(cx - bx);
dot = (dx * nx) + (dy * ny);
if (dot > 0)
break precheck;
dx = cx - x;
dy = cy - y;
nx = ay - cy;
ny = -(ax - cx);
dot = (dx * nx) + (dy * ny);
if (dot > 0)
break precheck;
if (curves) {
var curvey0:number = curves[id0 * curveDim + 2];
var curvey1:number = curves[id1 * curveDim + 2];
var curvey2:number = curves[id2 * curveDim + 2];
//check if not solid
if (curvey0 || curvey1 || curvey2) {
var v0x:number = bx - ax;
var v0y:number = by - ay;
var v1x:number = cx - ax;
var v1y:number = cy - ay;
var v2x:number = x - ax;
var v2y:number = y - ay;
var den:number = v0x * v1y - v1x * v0y;
var v:number = (v2x * v1y - v1x * v2y) / den;
var w:number = (v0x * v2y - v2x * v0y) / den;
//var u:number = 1 - v - w; //commented out as inlined away
//here be dragons
var uu:number = 0.5 * v + w;
var vv:number = w;
var d:number = uu * uu - vv;
var az:number = curves[id0 * curveDim];
if (d > 0 && az == -128) {
break precheck;;
} else if (d < 0 && az == 127) {
break precheck;;
}
}
}
return true;
}
}
//hard coded min vertex count to bother using a grid for
if (count > 150) {
var cells:Array<Array<number>> = triangleElements.cells;
var divisions:number = cells.length? triangleElements.divisions : (triangleElements.divisions = Math.min(Math.ceil(Math.sqrt(count)), 32));
var conversionX:number = divisions/boundingBox.width;
var conversionY:number = divisions/boundingBox.height;
var minx:number = boundingBox.x;
var miny:number = boundingBox.y;
if (!cells.length) { //build grid
//now we have bounds start creating grid cells and filling
cells.length = divisions * divisions;
for(var k:number = 0; k < count; k+=3) {
id0 = k + 2;
id1 = k + 1;
id2 = k + 0;
ax = positions[id0 * posDim];
ay = positions[id0 * posDim + 1];
bx = positions[id1 * posDim];
by = positions[id1 * posDim + 1];
cx = positions[id2 * posDim];
cy = positions[id2 * posDim + 1];
//subtractions to push into positive space
var min_index_x:number = Math.floor((Math.min(ax, bx, cx) - minx)*conversionX);
var min_index_y:number = Math.floor((Math.min(ay, by, cy) - miny)*conversionY);
var max_index_x:number = Math.floor((Math.max(ax, bx, cx) - minx)*conversionX);
var max_index_y:number = Math.floor((Math.max(ay, by, cy) - miny)*conversionY);
for (var i:number = min_index_x; i <= max_index_x; i++) {
for (var j:number = min_index_y; j <= max_index_y; j++) {
var index:number = i + j*divisions;
var nodes:Array<number> = cells[index] || (cells[index] = new Array<number>());
//push in the triangle ids
nodes.push(id0, id1, id2);
}
}
}
}
var index_x:number = Math.floor((x - minx)*conversionX);
var index_y:number = Math.floor((y - miny)*conversionY);
if ((index_x < 0 || index_x > divisions || index_y < 0 || index_y > divisions))
return false;
var nodes:Array<number> = cells[index_x + index_y*divisions];
if (nodes == null)
return false;
var nodeCount:number = nodes.length;
for (var k:number = 0; k < nodeCount; k += 3) {
id0 = nodes[k];
id1 = nodes[k + 1];
id2 = nodes[k + 2];
if(id2 == index) continue;
ax = positions[id0 * posDim];
ay = positions[id0 * posDim + 1];
bx = positions[id1 * posDim];
by = positions[id1 * posDim + 1];
cx = positions[id2 * posDim];
cy = positions[id2 * posDim + 1];
//from a to p
var dx:number = ax - x;
var dy:number = ay - y;
//edge normal (a-b)
var nx:number = by - ay;
var ny:number = -(bx - ax);
var dot:number = (dx * nx) + (dy * ny);
if (dot > 0)
continue;
dx = bx - x;
dy = by - y;
nx = cy - by;
ny = -(cx - bx);
dot = (dx * nx) + (dy * ny);
if (dot > 0)
continue;
dx = cx - x;
dy = cy - y;
nx = ay - cy;
ny = -(ax - cx);
dot = (dx * nx) + (dy * ny);
if (dot > 0)
continue;
if (curves) {
var curvey0:number = curves[id0 * curveDim + 2];
var curvey1:number = curves[id1 * curveDim + 2];
var curvey2:number = curves[id2 * curveDim + 2];
//check if not solid
if (curvey0 || curvey1 || curvey2) {
var v0x:number = bx - ax;
var v0y:number = by - ay;
var v1x:number = cx - ax;
var v1y:number = cy - ay;
var v2x:number = x - ax;
var v2y:number = y - ay;
var den:number = v0x * v1y - v1x * v0y;
var v:number = (v2x * v1y - v1x * v2y) / den;
var w:number = (v0x * v2y - v2x * v0y) / den;
//var u:number = 1 - v - w; //commented out as inlined away
//here be dragons
var uu:number = 0.5 * v + w;
var vv:number = w;
var d:number = uu * uu - vv;
var az:number = curves[id0 * curveDim];
if (d > 0 && az == -128)
continue;
else if (d < 0 && az == 127)
continue;
}
}
triangleElements.lastCollisionIndex = id2;
return true;
}
return false;
}
//brute force
for(var k:number = 0; k < count; k += 3) {
id0 = k + 2;
id1 = k + 1;
id2 = k + 0;
if(id2 == index) continue;
ax = positions[id0 * posDim];
ay = positions[id0 * posDim + 1];
bx = positions[id1 * posDim];
by = positions[id1 * posDim + 1];
cx = positions[id2 * posDim];
cy = positions[id2 * posDim + 1];
//console.log(ax, ay, bx, by, cx, cy);
//from a to p
var dx:number = ax - x;
var dy:number = ay - y;
//edge normal (a-b)
var nx:number = by - ay;
var ny:number = -(bx - ax);
//console.log(ax,ay,bx,by,cx,cy);
var dot:number = (dx * nx) + (dy * ny);
if (dot > 0)
continue;
dx = bx - x;
dy = by - y;
nx = cy - by;
ny = -(cx - bx);
dot = (dx * nx) + (dy * ny);
if (dot > 0)
continue;
dx = cx - x;
dy = cy - y;
nx = ay - cy;
ny = -(ax - cx);
dot = (dx * nx) + (dy * ny);
if (dot > 0)
continue;
if (curves) {
var curvey0:number = curves[id0 * curveDim + 2];
var curvey1:number = curves[id1 * curveDim + 2];
var curvey2:number = curves[id2 * curveDim + 2];
//check if not solid
if (curvey0 || curvey1 || curvey2) {
var v0x:number = bx - ax;
var v0y:number = by - ay;
var v1x:number = cx - ax;
var v1y:number = cy - ay;
var v2x:number = x - ax;
var v2y:number = y - ay;
var den:number = v0x * v1y - v1x * v0y;
var v:number = (v2x * v1y - v1x * v2y) / den;
var w:number = (v0x * v2y - v2x * v0y) / den;
//var u:number = 1 - v - w; //commented out as inlined away
//here be dragons
var uu:number = 0.5 * v + w;
var vv:number = w;
var d:number = uu * uu - vv;
var az:number = curves[id0 * curveDim];
if (d > 0 && az == -128) {
continue;
} else if (d < 0 && az == 127) {
continue;
}
}
}
triangleElements.lastCollisionIndex = id2;
return true;
}
return false;
}
public static getTriangleGraphicsBoxBounds(positionAttributes:AttributesView, output:Box, count:number, offset:number = 0):Box
{
var positions:ArrayBufferView = positionAttributes.get(count, offset);
var posDim:number = positionAttributes.dimensions;
if (output == null)
output = new Box();
var pos:number;
var minX:number = 0, minY:number = 0, minZ:number = 0;
var maxX:number = 0, maxY:number = 0, maxZ:number = 0;
var len:number = count*posDim;
for (var i:number = 0; i < len; i += posDim) {
if (i == 0) {
maxX = minX = positions[i];
maxY = minY = positions[i + 1];
maxZ = minZ = (posDim == 3)? positions[i + 2] : 0;
} else {
pos = positions[i];
if (pos < minX)
minX = pos;
else if (pos > maxX)
maxX = pos;
pos = positions[i + 1];
if (pos < minY)
minY = pos;
else if (pos > maxY)
maxY = pos;
if (posDim == 3) {
pos = positions[i + 2];
if (pos < minZ)
minZ = pos;
else if (pos > maxZ)
maxZ = pos;
}
}
}
if (output.x > minX)
output.x = minX;
if (output.y > minY)
output.y = minY;
if (output.z > minZ)
output.z = minZ;
if (output.right < maxX)
output.right = maxX;
if (output.bottom < maxY)
output.bottom = maxY;
if (output.back < maxZ)
output.back = maxZ;
return output;
}
public static getTriangleGraphicsSphereBounds(positionAttributes:AttributesView, center:Vector3D, output:Sphere, count:number, offset:number = 0):Sphere
{
var positions:ArrayBufferView = positionAttributes.get(count, offset);
var posDim:number = positionAttributes.dimensions;
if (output == null)
output = new Sphere();
var maxRadiusSquared:number = 0;
var radiusSquared:number;
var len = count*posDim;
var distanceX:number;
var distanceY:number;
var distanceZ:number;
for (var i:number = 0; i < len; i += posDim) {
distanceX = positions[i] - center.x;
distanceY = positions[i + 1] - center.y;
distanceZ = (posDim == 3)? positions[i + 2] - center.z : -center.z;
radiusSquared = distanceX*distanceX + distanceY*distanceY + distanceZ*distanceZ;
if (maxRadiusSquared < radiusSquared)
maxRadiusSquared = radiusSquared;
}
output.x = center.x;
output.y = center.y;
output.z = center.z;
output.radius = Math.sqrt(maxRadiusSquared);
return output;
}
}
export default ElementsUtils;