| // Copyright 2011 The Emscripten Authors. All rights reserved. |
| // Emscripten is available under two separate licenses, the MIT license and the |
| // University of Illinois/NCSA Open Source License. Both these licenses can be |
| // found in the LICENSE file. |
| |
| // From https://github.com/chadaustin/Web-Benchmarks/blob/master/skinning_test_no_simd.cpp |
| // Modifications: |
| // 1. Run for a fixed # of iterations, so the total runtime is the benchmark |
| // 2. Not have so much stuff on the stack in main() |
| // |
| // 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 <stdlib.h> |
| |
| struct CalBase4 { |
| float x, y, z, w; |
| |
| void set(float _x, float _y, float _z, float _w) { |
| x = _x; |
| y = _y; |
| z = _z; |
| w = _w; |
| } |
| }; |
| |
| struct CalVector4 : CalBase4 { |
| CalVector4() { |
| x = 0.0f; |
| y = 0.0f; |
| z = 0.0f; |
| w = 0.0f; |
| } |
| |
| CalVector4(float x, float y, float z, float w = 0.0f) { |
| this->x = x; |
| this->y = y; |
| this->z = z; |
| this->w = w; |
| } |
| |
| void setAsVector(float x, float y, float z) { |
| this->x = x; |
| this->y = y; |
| this->z = z; |
| w = 0.0f; |
| } |
| }; |
| |
| struct CalPoint4 : CalBase4 { |
| CalPoint4() { |
| x = 0.0f; |
| y = 0.0f; |
| z = 0.0f; |
| w = 1.0f; |
| } |
| |
| CalPoint4(float x, float y, float z, float w = 1.0f) { |
| this->x = x; |
| this->y = y; |
| this->z = z; |
| this->w = w; |
| } |
| |
| void setAsPoint(float x, float y, float z) { |
| x = this->x; |
| y = this->y; |
| z = this->z; |
| w = 1.0f; |
| } |
| }; |
| |
| // 3x3 transform matrix plus a translation 3-vector (stored in the w components |
| // of the rows. |
| struct BoneTransform { |
| CalVector4 rowx; |
| CalVector4 rowy; |
| CalVector4 rowz; |
| }; |
| |
| struct Influence |
| { |
| Influence() { |
| boneId = -1; |
| weight = 0.0f; |
| lastInfluenceForThisVertex = 0; |
| } |
| |
| Influence(unsigned b, float w, bool last) { |
| boneId = b; |
| weight = w; |
| lastInfluenceForThisVertex = last ? 1 : 0; |
| } |
| |
| unsigned boneId; |
| float weight; |
| unsigned lastInfluenceForThisVertex; |
| }; |
| |
| struct Vertex |
| { |
| CalPoint4 position; |
| CalVector4 normal; |
| }; |
| |
| inline void ScaleMatrix(BoneTransform& result, const BoneTransform& mat, const float 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; |
| } |
| inline void AddScaledMatrix(BoneTransform& result, const BoneTransform& mat, const float 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; |
| } |
| inline void TransformPoint(CalVector4& result, const BoneTransform& m, const 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; |
| } |
| inline void TransformVector(CalVector4& result, const BoneTransform& m, const 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( |
| const BoneTransform* boneTransforms, |
| int vertexCount, |
| const Vertex* vertices, |
| const Influence* influences, |
| CalVector4* output_vertex |
| ) { |
| |
| BoneTransform total_transform; |
| |
| // calculate all submesh vertices |
| while (vertexCount--) { |
| ScaleMatrix(total_transform, boneTransforms[influences->boneId], influences->weight); |
| |
| while (!influences++->lastInfluenceForThisVertex) { |
| AddScaledMatrix(total_transform, boneTransforms[influences->boneId], influences->weight); |
| } |
| |
| TransformPoint(output_vertex[0], total_transform, vertices->position); |
| TransformVector(output_vertex[1], total_transform, vertices->normal); |
| ++vertices; |
| output_vertex += 2; |
| } |
| } |
| |
| int main(int argc, char **argv) { |
| int N, M; |
| int arg = argc > 1 ? argv[1][0] - '0' : 3; |
| switch(arg) { |
| case 0: return 0; break; |
| case 1: N = 2000; M = 1700; break; |
| case 2: N = 6600; M = 6500; break; |
| case 3: N = 9500; M = 10000; break; |
| case 4: N = 2*11000; M = 2*12000; break; |
| case 5: N = 3*10000; M = 3*10800; break; |
| default: printf("error: %d\\n", arg); return -1; |
| } |
| |
| Vertex *v = new Vertex[N]; |
| Influence *i = new Influence[N]; |
| for (int k = 0; k < N; ++k) { |
| v[k].position.setAsPoint(1.0f, 2.0f, 3.0f); |
| v[k].normal.setAsVector(0.0f, 0.0f, 1.0f); |
| i[k].boneId = 0; |
| i[k].weight = 1.0f; |
| i[k].lastInfluenceForThisVertex = true; |
| } |
| |
| BoneTransform bt; |
| memset(&bt, 0, sizeof(bt)); |
| |
| CalVector4 *output = new CalVector4[N * 2]; |
| |
| for (unsigned j = 0; j < M; j++) |
| calculateVerticesAndNormals_x87(&bt, N, v, i, output); |
| |
| float sum = 0; |
| for (unsigned j = 0; j < N * 2; ++j) { |
| sum += (output[j].x + output[j].y + output[j].z + output[j].w); |
| } |
| |
| printf("blah=%f\n", sum); |
| } |
| |