Add cube, cylinder, and sphere mesh generators
Contributed by Brandon Jones
Signed-off-by: John McCutchan <john@johnmccutchan.com>
diff --git a/AUTHORS.txt b/AUTHORS.txt
index 3a1c1e7..5fe18b0 100644
--- a/AUTHORS.txt
+++ b/AUTHORS.txt
@@ -4,5 +4,6 @@
Contributors:
-Adam Singer <financeCoding@gmail.com>
+Brandon Jones <bajones@google.com>
Don Olmstead <don.j.olmstead@gmail.com>
+Adam Singer <financeCoding@gmail.com>
diff --git a/ChangeLog.txt b/ChangeLog.txt
index 38c0e70..90eef2a 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -1,3 +1,7 @@
+v 1.4.0 - November 2013
+
+- Add basic mesh generators (contributed by Brandon Jones)
+
v 1.3.5 - July 2013
- Class names now start with upper case, following Dart style guide.
@@ -59,7 +63,7 @@
v 0.8.5 - July 29 2012
- 33% faster matrix matrix multiply
-- Fix generated operator[]=
+- Fix generated operator[]=
- Fix OpenGL lookat and perspective matrix constructors
- Fix mat4x4 rotation constructors
- Fix mat4x4 multiplied with vector3 not applying translation
@@ -85,7 +89,7 @@
- Fixed adjoint matrix code generation
- Added selfAdd, selfSub, selfScale and selfNegate to matrix classes
- Added serialization support for Float32Array and Vectors/Matrices
-
-v 0.0.0 - March 20 2012
+
+v 0.0.0 - March 20 2012
- Initial release
diff --git a/bin/mesh_generator.dart b/bin/mesh_generator.dart
new file mode 100644
index 0000000..4199184
--- /dev/null
+++ b/bin/mesh_generator.dart
@@ -0,0 +1,94 @@
+/*
+ Copyright (C) 2013 John McCutchan <john@johnmccutchan.com>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+*/
+
+library vector_math_mesh_generator;
+
+import 'dart:convert';
+import 'package:vector_math/vector_math_geometry.dart';
+
+MeshGeometry generateCube(List<String> args) {
+ if (args.length != 3) {
+ return null;
+ }
+ num width = double.parse(args[0]);
+ num height = double.parse(args[1]);
+ num depth = double.parse(args[2]);
+ var generator = new CubeGenerator();
+ MeshGeometry geometry = generator.createCube(width, height, depth);
+ return geometry;
+}
+
+MeshGeometry generateSphere(List<String> args) {
+ if (args.length != 1) {
+ return null;
+ }
+ num radius = double.parse(args[0]);
+ var generator = new SphereGenerator();
+ MeshGeometry geometry = generator.createSphere(radius);
+ return geometry;
+}
+
+MeshGeometry generateCylinder(List<String> args) {
+ if (args.length != 3) {
+ return null;
+ }
+ num topRadius = double.parse(args[0]);
+ num bottomRadius = double.parse(args[1]);
+ num height = double.parse(args[2]);
+ var generator = new CylinderGenerator();
+ MeshGeometry geometry = generator.createCylinder(topRadius, bottomRadius,
+ height);
+ return geometry;
+}
+
+Map<String, Function> generators = {
+ 'cube': generateCube,
+ 'sphere': generateSphere,
+ 'cylinder': generateCylinder
+};
+
+
+main(List<String> args_) {
+ List<String> args = new List.from(args_, growable: true);
+
+ if (args.length == 0) {
+ print('mesh_generator.dart <type> [<arg0> ... <argN>]');
+ print('');
+ print('<type> = cube, sphere, cylinder');
+ print('mesh_generator.dart cube width height depth');
+ print('mesh_generator.dart sphere radius');
+ print('mesh_generator.dart cylinder topRadius bottomRadius height');
+ print('');
+ return;
+ }
+ var type = args.removeAt(0);
+ var generator = generators[type];
+ if (generator == null) {
+ print('Could not find generator for $type');
+ return;
+ }
+ MeshGeometry geometry = generator(args);
+ if (geometry == null) {
+ print('Error generating geometry for $type');
+ return;
+ }
+ print(JSON.encode(geometry));
+}
\ No newline at end of file
diff --git a/lib/src/vector_math_geometry/attribute_generators.dart b/lib/src/vector_math_geometry/attribute_generators.dart
index 589a7c6..58f59fa 100644
--- a/lib/src/vector_math_geometry/attribute_generators.dart
+++ b/lib/src/vector_math_geometry/attribute_generators.dart
@@ -27,9 +27,9 @@
void generateNormals(Vector3List normals, Vector3List positions,
Uint16List indices) {
Vector3 p0 = new Vector3.zero(),
- p1 = new Vector3.zero(),
- p2 = new Vector3.zero(),
- norm = new Vector3.zero();
+ p1 = new Vector3.zero(),
+ p2 = new Vector3.zero(),
+ norm = new Vector3.zero();
// Loop through every polygon, find it's normal, and add that to the vertex
// normals.
@@ -148,4 +148,5 @@
tangents.load(i, tan);
tangents[i] = tan.setValues(p0.x, p0.y, p0.z, sign);
}
-}
\ No newline at end of file
+}
+
diff --git a/lib/src/vector_math_geometry/cube_generator.dart b/lib/src/vector_math_geometry/cube_generator.dart
new file mode 100644
index 0000000..999c455
--- /dev/null
+++ b/lib/src/vector_math_geometry/cube_generator.dart
@@ -0,0 +1,128 @@
+/*
+ Copyright (C) 2013 John McCutchan <john@johnmccutchan.com>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+*/
+
+part of vector_math_geometry;
+
+class CubeGenerator extends GeometryGenerator {
+ double _width;
+ double _height;
+ double _depth;
+
+ int get vertexCount => 24;
+ int get indexCount => 36;
+
+ MeshGeometry createCube(num width, num height, num depth,
+ {flags: null}) {
+ _width = width.toDouble();
+ _height = height.toDouble();
+ _depth = depth.toDouble();
+
+ return _createGeometry(flags);
+ }
+
+ void _generateIndices(Uint16List indices) {
+ indices.setAll(0, [
+ 0, 1, 2, 0, 2, 3,
+ 4, 5, 6, 4, 6, 7,
+ 8, 9, 10, 8, 10, 11,
+ 12, 13, 14, 12, 14, 15,
+ 16, 17, 18, 16, 18, 19,
+ 20, 21, 22, 20, 22, 23
+ ]);
+ }
+
+ void _generatePositions(Vector3List positions, Uint16List indices) {
+ // Front
+ positions[0] = new Vector3(_width, _height, _depth);
+ positions[1] = new Vector3(-_width, _height, _depth);
+ positions[2] = new Vector3(-_width, -_height, _depth);
+ positions[3] = new Vector3(_width, -_height, _depth);
+
+ // Back
+ positions[4] = new Vector3(_width, -_height, -_depth);
+ positions[5] = new Vector3(-_width, -_height, -_depth);
+ positions[6] = new Vector3(-_width, _height, -_depth);
+ positions[7] = new Vector3(_width, _height, -_depth);
+
+ // Right
+ positions[8] = new Vector3(_width, -_height, _depth);
+ positions[9] = new Vector3(_width, -_height, -_depth);
+ positions[10] = new Vector3(_width, _height, -_depth);
+ positions[11] = new Vector3(_width, _height, _depth);
+
+ // Left
+ positions[12] = new Vector3(-_width, _height, _depth);
+ positions[13] = new Vector3(-_width, _height, -_depth);
+ positions[14] = new Vector3(-_width, -_height, -_depth);
+ positions[15] = new Vector3(-_width, -_height, _depth);
+
+ // Top
+ positions[16] = new Vector3(_width, _height, _depth);
+ positions[17] = new Vector3(_width, _height, -_depth);
+ positions[18] = new Vector3(-_width, _height, -_depth);
+ positions[19] = new Vector3(-_width, _height, _depth);
+
+ // Bottom
+ positions[20] = new Vector3(-_width, -_height, _depth);
+ positions[21] = new Vector3(-_width, -_height, -_depth);
+ positions[22] = new Vector3(_width, -_height, -_depth);
+ positions[23] = new Vector3(_width, -_height, _depth);
+ }
+
+ void _generateTexCoords(Vector2List texCoords, Vector3List positions,
+ Uint16List indices) {
+ // Front
+ texCoords[0] = new Vector2(1.0, 0.0);
+ texCoords[1] = new Vector2(0.0, 0.0);
+ texCoords[2] = new Vector2(0.0, 1.0);
+ texCoords[3] = new Vector2(1.0, 1.0);
+
+ // Back
+ texCoords[4] = new Vector2(0.0, 1.0);
+ texCoords[5] = new Vector2(1.0, 1.0);
+ texCoords[6] = new Vector2(1.0, 0.0);
+ texCoords[7] = new Vector2(0.0, 0.0);
+
+ // Right
+ texCoords[8] = new Vector2(0.0, 1.0);
+ texCoords[9] = new Vector2(1.0, 1.0);
+ texCoords[10] = new Vector2(1.0, 0.0);
+ texCoords[11] = new Vector2(0.0, 0.0);
+
+ // Left
+ texCoords[12] = new Vector2(1.0, 0.0);
+ texCoords[13] = new Vector2(0.0, 0.0);
+ texCoords[14] = new Vector2(0.0, 1.0);
+ texCoords[15] = new Vector2(1.0, 1.0);
+
+ // Top
+ texCoords[16] = new Vector2(1.0, 1.0);
+ texCoords[17] = new Vector2(1.0, 0.0);
+ texCoords[18] = new Vector2(0.0, 0.0);
+ texCoords[19] = new Vector2(0.0, 1.0);
+
+ // Bottom
+ texCoords[20] = new Vector2(0.0, 0.0);
+ texCoords[21] = new Vector2(0.0, 1.0);
+ texCoords[22] = new Vector2(1.0, 1.0);
+ texCoords[23] = new Vector2(1.0, 0.0);
+ }
+}
\ No newline at end of file
diff --git a/lib/src/vector_math_geometry/cylinder_generator.dart b/lib/src/vector_math_geometry/cylinder_generator.dart
new file mode 100644
index 0000000..f06c81f
--- /dev/null
+++ b/lib/src/vector_math_geometry/cylinder_generator.dart
@@ -0,0 +1,158 @@
+/*
+ Copyright (C) 2013 John McCutchan <john@johnmccutchan.com>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+*/
+
+part of vector_math_geometry;
+
+class CylinderGenerator extends GeometryGenerator {
+ double _topRadius;
+ double _bottomRadius;
+ double _height;
+ int _segments;
+
+ int get vertexCount => ((_segments + 1) * 2) + (_segments * 2);
+ int get indexCount => (_segments * 6) + ((_segments - 2) * 6);
+
+ MeshGeometry createCylinder(num topRadius, num bottomRadius,
+ num height, {int segments: 16, flags: null}) {
+ _topRadius = topRadius.toDouble();
+ _bottomRadius = bottomRadius.toDouble();
+ _height = height.toDouble();
+ _segments = segments;
+
+ return _createGeometry(flags);
+ }
+
+ void _generateIndices(Uint16List indices) {
+ int i = 0;
+
+ // Sides
+ int base1 = 0;
+ int base2 = _segments + 1;
+ for(int x = 0; x < _segments; ++x) {
+ indices[i++] = base1 + x;
+ indices[i++] = base1 + x + 1;
+ indices[i++] = base2 + x;
+
+ indices[i++] = base1 + x + 1;
+ indices[i++] = base2 + x + 1;
+ indices[i++] = base2 + x;
+ }
+
+ // Top cap
+ base1 = (_segments + 1) * 2;
+ for(int x = 1; x < _segments - 1; ++x) {
+ indices[i++] = base1;
+ indices[i++] = base1 + x + 1;
+ indices[i++] = base1 + x;
+ }
+
+ // Bottom cap
+ base1 = (_segments + 1) * 2 + _segments;
+ for(int x = 1; x < _segments - 1; ++x) {
+ indices[i++] = base1;
+ indices[i++] = base1 + x;
+ indices[i++] = base1 + x + 1;
+ }
+ }
+
+ void _generatePositions(Vector3List positions, Uint16List indices) {
+ int i = 0;
+
+ // Top
+ for (int x = 0; x <= _segments; ++x) {
+ double u = x / _segments;
+
+ positions[i++] = new Vector3(
+ _topRadius * Math.cos(u * Math.PI * 2.0),
+ _height * 0.5,
+ _topRadius * Math.sin(u * Math.PI * 2.0)
+ );
+ }
+
+ // Bottom
+ for (int x = 0; x <= _segments; ++x) {
+ double u = x / _segments;
+
+ positions[i++] = new Vector3(
+ _bottomRadius * Math.cos(u * Math.PI * 2.0),
+ _height * -0.5,
+ _bottomRadius * Math.sin(u * Math.PI * 2.0)
+ );
+ }
+
+ // Top cap
+ for (int x = 0; x < _segments; ++x) {
+ double u = x / _segments;
+
+ positions[i++] = new Vector3(
+ _topRadius * Math.cos(u * Math.PI * 2.0),
+ _height * 0.5,
+ _topRadius * Math.sin(u * Math.PI * 2.0)
+ );
+ }
+
+ // Bottom cap
+ for (int x = 0; x < _segments; ++x) {
+ double u = x / _segments;
+
+ positions[i++] = new Vector3(
+ _bottomRadius * Math.cos(u * Math.PI * 2.0),
+ _height * -0.5,
+ _bottomRadius * Math.sin(u * Math.PI * 2.0)
+ );
+ }
+ }
+
+ void _generateTexCoords(Vector2List texCoords, Vector3List positions,
+ Uint16List indices) {
+ int i = 0;
+
+ // Cylinder top
+ for (int x = 0; x <= _segments; ++x) {
+ double u = 1.0 - (x / _segments);
+ texCoords[i++] = new Vector2(u, 0.0);
+ }
+
+ // Cylinder bottom
+ for (int x = 0; x <= _segments; ++x) {
+ double u = 1.0 - (x / _segments);
+ texCoords[i++] = new Vector2(u, 1.0);
+ }
+
+ // Top cap
+ for (int x = 0; x < _segments; ++x) {
+ double r = (x / _segments) * Math.PI * 2.0;
+ texCoords[i++] = new Vector2(
+ (Math.cos(r) * 0.5 + 0.5),
+ (Math.sin(r) * 0.5 + 0.5)
+ );
+ }
+
+ // Bottom cap
+ for (int x = 0; x < _segments; ++x) {
+ double r = (x / _segments) * Math.PI * 2.0;
+ texCoords[i++] = new Vector2(
+ (Math.cos(r) * 0.5 + 0.5),
+ (Math.sin(r) * 0.5 + 0.5)
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/src/vector_math_geometry/geometry_generator.dart b/lib/src/vector_math_geometry/geometry_generator.dart
new file mode 100644
index 0000000..9dd3f46
--- /dev/null
+++ b/lib/src/vector_math_geometry/geometry_generator.dart
@@ -0,0 +1,153 @@
+/*
+ Copyright (C) 2013 John McCutchan <john@johnmccutchan.com>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+*/
+
+part of vector_math_geometry;
+
+class GeometryGeneratorFlags {
+ final bool texCoords;
+ final bool normals;
+ final bool tangents;
+ final bool invertFaces;
+
+ GeometryGeneratorFlags({this.texCoords: true,
+ this.normals: true,
+ this.tangents: true,
+ this.invertFaces: false});
+}
+
+abstract class GeometryGenerator {
+ int get vertexCount;
+ int get indexCount;
+
+ MeshGeometry _createGeometry(GeometryGeneratorFlags flags) {
+ MeshGeometry mesh = new MeshGeometry();
+
+ if (flags == null)
+ flags = new GeometryGeneratorFlags();
+
+ int stride = 12; // Position
+ if (flags.texCoords || flags.tangents)
+ stride += 8;
+ if (flags.normals)
+ stride += 12;
+ if (flags.tangents)
+ stride += 16;
+
+ VertexAttrib positionAttrib;
+ VertexAttrib texCoordAttrib;
+ VertexAttrib normalAttrib;
+ VertexAttrib tangentAttrib;;
+
+ Vector2List texCoordView;
+ Vector3List positionView;
+ Vector3List normalView;
+ Vector4List tangentView;
+
+ mesh.buffer = new Float32List(vertexCount * (stride~/4));
+ mesh.indices = new Uint16List(indexCount);
+
+ _generateIndices(mesh.indices);
+
+ int offset = 0;
+
+ positionAttrib = new VertexAttrib('POSITION', 3, 'float', stride, offset);
+ mesh.addAttrib(positionAttrib);
+ offset += 12;
+ positionView = mesh.getViewForAttrib('POSITION');
+ _generatePositions(positionView, mesh.indices);
+
+ if (flags.texCoords || flags.tangents) {
+ texCoordAttrib = new VertexAttrib('TEXCOORD0', 2, 'float', stride,
+ offset);
+ mesh.addAttrib(texCoordAttrib);
+ offset += 8;
+ texCoordView = mesh.getViewForAttrib('TEXCOORD0');
+ _generateTexCoords(texCoordView, positionView, mesh.indices);
+ }
+
+ if (flags.normals) {
+ normalAttrib = new VertexAttrib('NORMAL', 3, 'float', stride, offset);
+ mesh.addAttrib(normalAttrib);
+ offset += 12;
+ normalView = mesh.getViewForAttrib('NORMAL');
+ _generateNormals(normalView, positionView, mesh.indices);
+ }
+
+ if (flags.tangents) {
+ tangentAttrib = new VertexAttrib('TANGENT', 4, 'float', stride, offset);
+ mesh.addAttrib(tangentAttrib);
+ offset += 16;
+ tangentView = mesh.getViewForAttrib('TANGENT');
+ _generateTangents(tangentView, positionView, normalView, texCoordView,
+ mesh.indices);
+ }
+
+ if (flags.invertFaces) {
+ _invertMeshFaces(mesh);
+ }
+
+ return mesh;
+ }
+
+ void _generateIndices(Uint16List indices);
+
+ void _generatePositions(Vector3List positions, Uint16List indices);
+
+ void _generateTexCoords(Vector2List texCoords, Vector3List positions,
+ Uint16List indices) {
+ for (int i = 0; i < positions.length; ++i) {
+ Vector3 p = positions[i];
+
+ // These are TERRIBLE texture coords, but it's better than nothing.
+ // Override this function and put better ones in place!
+ texCoords[i] = new Vector2(p.x + p.z, p.y + p.z);
+ }
+ }
+
+ void _generateNormals(Vector3List normals, Vector3List positions,
+ Uint16List indices) {
+ generateNormals(normals, positions, indices);
+ }
+
+ void _generateTangents(Vector4List tangents, Vector3List positions,
+ Vector3List normals, Vector2List texCoords,
+ Uint16List indices) {
+ generateTangents(tangents, positions, normals, texCoords, indices);
+ }
+
+ void _invertMeshFaces(MeshGeometry mesh) {
+ // Swap all the triangle indices
+ for (int i=0; i < mesh.indices.length; i += 3) {
+ int tmp = mesh.indices[i];
+ mesh.indices[i] = mesh.indices[i+2];
+ mesh.indices[i+2] = tmp;
+ }
+
+ Vector3List normals = mesh.getViewForAttrib('NORMAL');
+ if (normals != null) {
+ for(int i=0; i < normals.length; ++i) {
+ normals[i] = -normals[i];
+ }
+ }
+
+ // TODO: Do the tangents need to be inverted? Maybe just the W component?
+ }
+}
\ No newline at end of file
diff --git a/lib/src/vector_math_geometry/mesh_geometry.dart b/lib/src/vector_math_geometry/mesh_geometry.dart
new file mode 100644
index 0000000..94236b0
--- /dev/null
+++ b/lib/src/vector_math_geometry/mesh_geometry.dart
@@ -0,0 +1,117 @@
+/*
+ Copyright (C) 2013 John McCutchan <john@johnmccutchan.com>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+*/
+
+part of vector_math_geometry;
+
+class VertexAttrib {
+ final String name;
+ final String type;
+ final int size;
+ final int stride;
+ final int offset;
+
+ VertexAttrib(this.name, this.size, this.type, this.stride, this.offset);
+
+ VectorList getView(Float32List buffer) {
+ int viewOffset = offset ~/ buffer.elementSizeInBytes;
+ int viewStride = stride ~/ buffer.elementSizeInBytes;
+ switch(size) {
+ case 2:
+ return new Vector2List.view(buffer, viewOffset, viewStride);
+ case 3:
+ return new Vector3List.view(buffer, viewOffset, viewStride);
+ case 4:
+ return new Vector4List.view(buffer, viewOffset, viewStride);
+ }
+ }
+
+ String get format {
+ return '$type$size';
+ }
+
+ Map toJson() {
+ return {
+ 'format': format,
+ 'name': name,
+ 'offset': offset,
+ 'stride': stride,
+ 'size': size,
+ 'type': type
+ };
+ }
+}
+
+class MeshGeometry {
+ Float32List buffer;
+ Uint16List indices;
+ List<VertexAttrib> attribs = new List<VertexAttrib>();
+
+ MeshGeometry() {}
+
+ MeshGeometry.fromJson(Map json) {
+ buffer = new Float32List.fromList(json["buffer"]);
+
+ if (json.containsKey("indices")) {
+ indices = new Uint16List.fromList(json["indices"]);
+ }
+
+ Map jsonAttribs = json["attribs"];
+ for (String key in jsonAttribs.keys) {
+ addAttrib(attribFromJson(key, jsonAttribs[key]));
+ }
+ }
+
+ Map toJson() {
+ Map r = {};
+ r['attributes'] = attribs;
+ r['indices'] = indices;
+ r['vertices'] = buffer;
+ return r;
+ }
+
+ static VertexAttrib attribFromJson(String name, Map json) {
+ return new VertexAttrib(name,
+ json["size"],
+ json["format"],
+ json["stride"],
+ json["offset"]);
+ }
+
+ // Estimates the number of vertices contained in this mesh
+ int get length {
+ if (attribs == null || attribs.length == 0)
+ return 0;
+ VertexAttrib a = attribs[0];
+ return buffer.lengthInBytes ~/ a.stride;
+ }
+
+ void addAttrib(VertexAttrib attrib) {
+ attribs.add(attrib);
+ }
+
+ dynamic getViewForAttrib(String name) {
+ for (VertexAttrib attrib in attribs) {
+ if (attrib.name == name)
+ return attrib.getView(buffer);
+ }
+ return null;
+ }
+}
diff --git a/lib/src/vector_math_geometry/sphere_generator.dart b/lib/src/vector_math_geometry/sphere_generator.dart
new file mode 100644
index 0000000..229ab32
--- /dev/null
+++ b/lib/src/vector_math_geometry/sphere_generator.dart
@@ -0,0 +1,110 @@
+/*
+ Copyright (C) 2013 John McCutchan <john@johnmccutchan.com>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+*/
+
+part of vector_math_geometry;
+
+class SphereGenerator extends GeometryGenerator {
+ double _radius;
+ int _latSegments;
+ int _lonSegments;
+
+ int get vertexCount => (_lonSegments + 1) * (_latSegments + 1);
+ int get indexCount => 6 * _lonSegments * _latSegments;
+
+ MeshGeometry createSphere(num radius, {int latSegments: 16,
+ int lonSegments: 16, flags: null}) {
+ _radius = radius.toDouble();
+ _latSegments = latSegments;
+ _lonSegments = lonSegments;
+
+ return _createGeometry(flags);
+ }
+
+ void _generateIndices(Uint16List indices) {
+ int i = 0;
+ for (int y = 0; y < _latSegments; ++y) {
+ int base1 = (_lonSegments + 1) * y;
+ int base2 = (_lonSegments + 1) * (y+1);
+
+ for(int x = 0; x < _lonSegments; ++x) {
+ indices[i++] = base1 + x;
+ indices[i++] = base1 + x + 1;
+ indices[i++] = base2 + x;
+
+ indices[i++] = base1 + x + 1;
+ indices[i++] = base2 + x + 1;
+ indices[i++] = base2 + x;
+ }
+ }
+ }
+
+ void _generatePositions(Vector3List positions, Uint16List indices) {
+ int i = 0;
+ for (int y = 0; y <= _latSegments; ++y) {
+ double v = y / _latSegments;
+ double sv = Math.sin(v * Math.PI);
+ double cv = Math.cos(v * Math.PI);
+
+ for (int x = 0; x <= _lonSegments; ++x) {
+ double u = x / _lonSegments;
+
+ positions[i++] = new Vector3(
+ _radius * Math.cos(u * Math.PI * 2.0) * sv,
+ _radius * cv,
+ _radius * Math.sin(u * Math.PI * 2.0) * sv
+ );
+ }
+ }
+ }
+
+ void _generateTexCoords(Vector2List texCoords, Vector3List positions,
+ Uint16List indices) {
+ int i = 0;
+ for (int y = 0; y <= _latSegments; ++y) {
+ double v = y / _latSegments;
+
+ for (int x = 0; x <= _lonSegments; ++x) {
+ double u = x / _lonSegments;
+ texCoords[i++] = new Vector2(u, v);
+ }
+ }
+ }
+
+ void _generateNormals(Vector3List normals, Vector3List positions,
+ Uint16List indices) {
+ int i = 0;
+ for (int y = 0; y <= _latSegments; ++y) {
+ double v = y / _latSegments;
+ double sv = Math.sin(v * Math.PI);
+ double cv = Math.cos(v * Math.PI);
+
+ for (int x = 0; x <= _lonSegments; ++x) {
+ double u = x / _lonSegments;
+
+ normals[i++] = new Vector3(
+ Math.cos(u * Math.PI * 2.0) * sv,
+ cv,
+ Math.sin(u * Math.PI * 2.0) * sv
+ );
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/src/vector_math_operations/matrix.dart b/lib/src/vector_math_operations/matrix.dart
index 569bc4e..f6935bc 100644
--- a/lib/src/vector_math_operations/matrix.dart
+++ b/lib/src/vector_math_operations/matrix.dart
@@ -306,7 +306,7 @@
b2.shuffle(Float32x4.ZZZZ) * a2 +
b2.shuffle(Float32x4.WWWW) * a3;
var b3 = B[bOffset++];
- out[outOffset++] = b3.shuffle(Float32x4.XXXX)*a0 +
+ out[outOffset++] = b3.shuffle(Float32x4.XXXX) * a0 +
b3.shuffle(Float32x4.YYYY) * a1 +
b3.shuffle(Float32x4.ZZZZ) * a2 +
b3.shuffle(Float32x4.WWWW) * a3;
diff --git a/lib/vector_math_geometry.dart b/lib/vector_math_geometry.dart
index f2ba469..7a688c5 100644
--- a/lib/vector_math_geometry.dart
+++ b/lib/vector_math_geometry.dart
@@ -20,8 +20,16 @@
*/
library vector_math_geometry;
+
import 'dart:typed_data';
+import 'dart:math' as Math;
+
import 'package:vector_math/vector_math.dart';
import 'package:vector_math/vector_math_lists.dart';
part 'src/vector_math_geometry/attribute_generators.dart';
+part 'src/vector_math_geometry/cube_generator.dart';
+part 'src/vector_math_geometry/cylinder_generator.dart';
+part 'src/vector_math_geometry/geometry_generator.dart';
+part 'src/vector_math_geometry/mesh_geometry.dart';
+part 'src/vector_math_geometry/sphere_generator.dart';