Last active
December 15, 2015 21:49
-
-
Save andyfriesen/5328124 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:html'; | |
/* | |
// compiled in cygwin with: | |
// g++ -Wall -O2 -o skinning_test_no_simd skinning_test_no_simd.cpp | |
#include <vector> | |
#include <set> | |
#include <map> | |
#include <assert.h> | |
#include <math.h> | |
#include <string.h> | |
#include <stdio.h> | |
#include <time.h> | |
#define CAL3D_ALIGN_HEAD(N) | |
#define CAL3D_ALIGN_TAIL(N) | |
*/ | |
class CalBase4 { | |
double x, y, z, w; | |
void set(double _x, double _y, double _z, double _w) { | |
x = _x; | |
y = _y; | |
z = _z; | |
w = _w; | |
} | |
} | |
//CAL3D_ALIGN_TAIL(16); | |
class CalVector4 extends CalBase4 { | |
CalVector4() { | |
x = 0.0; | |
y = 0.0; | |
z = 0.0; | |
w = 0.0; | |
} | |
CalVector4.fromComponents3(double x, double y, double z) | |
: this.fromComponents(x, y, z, 0.0); | |
CalVector4.fromComponents(double x, double y, double z, double w) { | |
this.x = x; | |
this.y = y; | |
this.z = z; | |
this.w = w; | |
} | |
void setAsVector(double x, double y, double z) { | |
this.x = x; | |
this.y = y; | |
this.z = z; | |
this.w = 0.0; | |
} | |
} | |
class CalPoint4 extends CalBase4 { | |
CalPoint4() { | |
x = 0.0; | |
y = 0.0; | |
z = 0.0; | |
w = 1.0; | |
} | |
CalPoint4.fromComponents(double x, double y, double z, double w) { | |
this.x = x; | |
this.y = y; | |
this.z = z; | |
this.w = w; | |
} | |
CalPoint4.fromComponents3(double x, double y, double z) | |
: this.fromComponents(x, y, z, 1.0); | |
void setAsPoint(double x, double y, double z) { | |
x = this.x; | |
y = this.y; | |
z = this.z; | |
this.w = 1.0; | |
} | |
} | |
// 3x3 transform matrix plus a translation 3-vector (stored in the w components | |
// of the rows. This struct needs to be 16-byte aligned for SSE. | |
class BoneTransform { | |
CalVector4 rowx; | |
CalVector4 rowy; | |
CalVector4 rowz; | |
BoneTransform() | |
: rowx = new CalVector4() | |
, rowy = new CalVector4() | |
, rowz = new CalVector4(); | |
} | |
class Influence { | |
Influence() | |
: this.fromData(-1, 0.0, false); | |
Influence.fromData(int b, double w, bool last) { | |
boneId = b; | |
weight = w; | |
lastInfluenceForThisVertex = last ? 1 : 0; | |
} | |
int boneId; | |
double weight; | |
int lastInfluenceForThisVertex; | |
} | |
class Vertex { | |
CalPoint4 position; | |
CalVector4 normal; | |
Vertex() | |
: position = new CalPoint4() | |
, normal = new CalVector4.fromComponents(1.0, 0.0, 0.0, 0.0); | |
} | |
void ScaleMatrix(BoneTransform result, BoneTransform mat, double s) { | |
var x = mat.rowx; | |
var y = mat.rowy; | |
var z = mat.rowz; | |
result.rowx.x = s * x.x; | |
result.rowx.y = s * x.y; | |
result.rowx.z = s * x.z; | |
result.rowx.w = s * x.w; | |
result.rowy.x = s * y.x; | |
result.rowy.y = s * y.y; | |
result.rowy.z = s * y.z; | |
result.rowy.w = s * y.w; | |
result.rowz.x = s * z.x; | |
result.rowz.y = s * z.y; | |
result.rowz.z = s * z.z; | |
result.rowz.w = s * z.w; | |
} | |
void AddScaledMatrix(BoneTransform result, BoneTransform mat, double s) { | |
result.rowx.x += s * mat.rowx.x; | |
result.rowx.y += s * mat.rowx.y; | |
result.rowx.z += s * mat.rowx.z; | |
result.rowx.w += s * mat.rowx.w; | |
result.rowy.x += s * mat.rowy.x; | |
result.rowy.y += s * mat.rowy.y; | |
result.rowy.z += s * mat.rowy.z; | |
result.rowy.w += s * mat.rowy.w; | |
result.rowz.x += s * mat.rowz.x; | |
result.rowz.y += s * mat.rowz.y; | |
result.rowz.z += s * mat.rowz.z; | |
result.rowz.w += s * mat.rowz.w; | |
} | |
void TransformPoint(CalVector4 result, BoneTransform m, CalBase4 v) { | |
result.x = m.rowx.x * v.x + m.rowx.y * v.y + m.rowx.z * v.z + m.rowx.w; | |
result.y = m.rowy.x * v.x + m.rowy.y * v.y + m.rowy.z * v.z + m.rowy.w; | |
result.z = m.rowz.x * v.x + m.rowz.y * v.y + m.rowz.z * v.z + m.rowz.w; | |
} | |
void TransformVector(CalVector4 result, BoneTransform m, CalBase4 v) { | |
result.x = m.rowx.x * v.x + m.rowx.y * v.y + m.rowx.z * v.z; | |
result.y = m.rowy.x * v.x + m.rowy.y * v.y + m.rowy.z * v.z; | |
result.z = m.rowz.x * v.x + m.rowz.y * v.y + m.rowz.z * v.z; | |
} | |
void calculateVerticesAndNormals_x87( | |
List<BoneTransform> boneTransforms, | |
int vertexCount, | |
List<Vertex> vertices, | |
List<Influence> influences, | |
List<CalVector4> output | |
) { | |
BoneTransform total_transform = new BoneTransform(); | |
int currentVertex = 0; | |
int currentInfluence = 0; | |
for (int sourceVertex = 0, sourceInfluence = 0, outputVertex = 0; | |
sourceVertex < influences.length; | |
sourceVertex += 1, sourceInfluence += 1, outputVertex += 2 | |
) { | |
Influence currentInfluence = influences[sourceInfluence]; | |
ScaleMatrix(total_transform, boneTransforms[currentInfluence.boneId], currentInfluence.weight); | |
while (0 == currentInfluence.lastInfluenceForThisVertex) { | |
sourceInfluence += 1; | |
currentInfluence = influences[sourceInfluence]; | |
AddScaledMatrix(total_transform, boneTransforms[currentInfluence.boneId], currentInfluence.weight); | |
} | |
TransformPoint(output[outputVertex], total_transform, vertices[sourceVertex].position); | |
TransformVector(output[outputVertex + 1], total_transform, vertices[sourceVertex].normal); | |
} | |
} | |
int main() { | |
const N = 10000; | |
const CLOCKS_PER_SEC = 1; | |
List<Vertex> v = new List<Vertex>(N); | |
List<Influence> i = new List<Influence>(N); | |
for (int k = 0; k < N; ++k) { | |
v[k] = new Vertex(); | |
v[k].position.setAsPoint(1.0, 2.0, 3.0); | |
v[k].normal.setAsVector(0.0, 0.0, 1.0); | |
i[k] = new Influence.fromData(0, 1.0, true); | |
} | |
List<BoneTransform> bt = new List<BoneTransform>(); | |
bt.add(new BoneTransform()); | |
List<CalVector4> output = new List<CalVector4>(N * 2); | |
for (int k = 0; k < N * 2; ++k) { | |
output[k] = new CalVector4(); | |
} | |
int vertices_skinned = 0; | |
var start = new DateTime.now(); | |
var end = start.add(new Duration(seconds: 5)); | |
while (new DateTime.now().isBefore(end)) { | |
calculateVerticesAndNormals_x87(bt, N, v, i, output); | |
vertices_skinned += N; | |
} | |
var elapsed = (new DateTime.now()).difference(start); | |
num sum = 0; | |
for (int i = 0; i < N * 2; ++i) { | |
sum += (output[i].x + output[i].y + output[i].z + output[i].w); | |
} | |
int verticesPerSecond = (vertices_skinned / elapsed.inSeconds).floor(); | |
query("#sample_text_id").text = ["Skinned vertices per second: ", verticesPerSecond, ", blah=", sum].join(""); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment