Skip to content

Instantly share code, notes, and snippets.

@andyfriesen
Last active December 15, 2015 21:49

Revisions

  1. andyfriesen revised this gist Apr 7, 2013. 1 changed file with 35 additions and 12 deletions.
    47 changes: 35 additions & 12 deletions VertexSkinning.dart
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,23 @@
    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;

    @@ -11,6 +29,8 @@ class CalBase4 {
    }
    }

    //CAL3D_ALIGN_TAIL(16);

    class CalVector4 extends CalBase4 {
    CalVector4() {
    x = 0.0;
    @@ -102,18 +122,21 @@ class Vertex {


    void ScaleMatrix(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;
    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) {
  2. andyfriesen revised this gist Apr 6, 2013. 1 changed file with 0 additions and 20 deletions.
    20 changes: 0 additions & 20 deletions VertexSkinning.dart
    Original file line number Diff line number Diff line change
    @@ -1,23 +1,5 @@
    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;

    @@ -29,8 +11,6 @@ class CalBase4 {
    }
    }

    //CAL3D_ALIGN_TAIL(16);

    class CalVector4 extends CalBase4 {
    CalVector4() {
    x = 0.0;
  3. andyfriesen created this gist Apr 6, 2013.
    237 changes: 237 additions & 0 deletions VertexSkinning.dart
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,237 @@
    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) {
    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 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("");
    }