Skip to content

Instantly share code, notes, and snippets.

@andyfriesen
Last active December 15, 2015 21:49
Show Gist options
  • Save andyfriesen/5328124 to your computer and use it in GitHub Desktop.
Save andyfriesen/5328124 to your computer and use it in GitHub Desktop.
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