/// <summary> /// </summary> /// <param name="other"> /// </param> public virtual void merge(VertexData other) { if (other.indices != null) { if (this.indices == null) { this.indices = new Array <int>(); } var offset = (this.positions != null) ? this.positions.Length / 3 : 0; for (var index = 0; index < other.indices.Length; index++) { this.indices.Add(other.indices[index] + offset); } } if (other.positions != null) { if (this.positions == null) { this.positions = new Array <double>(); } for (var index = 0; index < other.positions.Length; index++) { this.positions.Add(other.positions[index]); } } if (other.normals != null) { if (this.normals == null) { this.normals = new Array <double>(); } for (var index = 0; index < other.normals.Length; index++) { this.normals.Add(other.normals[index]); } } if (other.uvs != null) { if (this.uvs == null) { this.uvs = new Array <double>(); } for (var index = 0; index < other.uvs.Length; index++) { this.uvs.Add(other.uvs[index]); } } if (other.uv2s != null) { if (this.uv2s == null) { this.uv2s = new Array <double>(); } for (var index = 0; index < other.uv2s.Length; index++) { this.uv2s.Add(other.uv2s[index]); } } if (other.matricesIndices != null) { if (this.matricesIndices == null) { this.matricesIndices = new Array <double>(); } for (var index = 0; index < other.matricesIndices.Length; index++) { this.matricesIndices.Add(other.matricesIndices[index]); } } if (other.matricesWeights != null) { if (this.matricesWeights == null) { this.matricesWeights = new Array <double>(); } for (var index = 0; index < other.matricesWeights.Length; index++) { this.matricesWeights.Add(other.matricesWeights[index]); } } if (other.colors != null) { if (this.colors == null) { this.colors = new Array <double>(); } for (var index = 0; index < other.colors.Length; index++) { this.colors.Add(other.colors[index]); } } }
/// <summary> /// </summary> /// <param name="xmin"> /// </param> /// <param name="zmin"> /// </param> /// <param name="xmax"> /// </param> /// <param name="zmax"> /// </param> /// <param name="subdivisions"> /// </param> /// <param name="precision"> /// </param> /// <returns> /// </returns> public static VertexData CreateTiledGround(double xmin, double zmin, double xmax, double zmax, SizeI subdivisions, SizeI precision) { var indices = new Array <int>(); var positions = new Array <double>(); var normals = new Array <double>(); var uvs = new Array <double>(); subdivisions.h = (subdivisions.w < 1) ? 1 : subdivisions.h; subdivisions.w = (subdivisions.w < 1) ? 1 : subdivisions.w; precision.w = (precision.w < 1) ? 1 : precision.w; precision.h = (precision.h < 1) ? 1 : precision.h; var tileSize = new SizeI { w = (int)((xmax - xmin) / subdivisions.w), h = (int)((zmax - zmin) / subdivisions.h) }; for (var tileRow = 0; tileRow < subdivisions.h; tileRow++) { for (var tileCol = 0; tileCol < subdivisions.w; tileCol++) { var xTileMin = xmin + tileCol * tileSize.w; var zTileMin = zmin + tileRow * tileSize.h; var xTileMax = xmin + (tileCol + 1) * tileSize.w; var zTileMax = zmin + (tileRow + 1) * tileSize.h; // Indices var _base = positions.Length / 3; var rowLength = precision.w + 1; for (var row = 0; row < precision.h; row++) { for (var col = 0; col < precision.w; col++) { var square = new Array <int>( _base + col + row * rowLength, _base + (col + 1) + row * rowLength, _base + (col + 1) + (row + 1) * rowLength, _base + col + (row + 1) * rowLength); indices.Add(square[1]); indices.Add(square[2]); indices.Add(square[3]); indices.Add(square[0]); indices.Add(square[1]); indices.Add(square[3]); } } // Position, normals and uvs var position = Vector3.Zero(); var normal = new Vector3(0, 1.0, 0); for (var row = 0; row <= precision.h; row++) { position.z = (row * (zTileMax - zTileMin)) / precision.h + zTileMin; for (var col = 0; col <= precision.w; col++) { position.x = (col * (xTileMax - xTileMin)) / precision.w + xTileMin; position.y = 0; positions.Add(position.x, position.y, position.z); normals.Add(normal.x, normal.y, normal.z); uvs.Add(col / precision.w, row / precision.h); } } } } var vertexData = new VertexData(); vertexData.indices = indices; vertexData.positions = positions; vertexData.normals = normals; vertexData.uvs = uvs; return(vertexData); }
/// <summary> /// </summary> /// <param name="radius"> /// </param> /// <param name="tube"> /// </param> /// <param name="radialSegments"> /// </param> /// <param name="tubularSegments"> /// </param> /// <param name="p"> /// </param> /// <param name="q"> /// </param> /// <returns> /// </returns> public static VertexData CreateTorusKnot( double radius = 2, double tube = 0.5, int radialSegments = 32, int tubularSegments = 32, double p = 2, double q = 3) { var indices = new Array <int>(); var positions = new Array <double>(); var normals = new Array <double>(); var uvs = new Array <double>(); var getPos = new Func <double, Vector3>( angle => { var cu = Math.Cos(angle); var su = Math.Sin(angle); var quOverP = q / p * angle; var cs = Math.Cos(quOverP); var tx = radius * (2 + cs) * 0.5 * cu; var ty = radius * (2 + cs) * su * 0.5; var tz = radius * Math.Sin(quOverP) * 0.5; return(new Vector3(tx, ty, tz)); }); for (var i = 0; i <= radialSegments; i++) { var modI = i % radialSegments; var u = modI / radialSegments * 2 * p * Math.PI; var p1 = getPos(u); var p2 = getPos(u + 0.01); var tang = p2.subtract(p1); var n = p2.add(p1); var bitan = Vector3.Cross(tang, n); n = Vector3.Cross(bitan, tang); bitan.normalize(); n.normalize(); for (var j = 0; j < tubularSegments; j++) { var modJ = j % tubularSegments; var v = modJ / tubularSegments * 2 * Math.PI; var cx = -tube *Math.Cos(v); var cy = tube * Math.Sin(v); positions.Add(p1.x + cx * n.x + cy * bitan.x); positions.Add(p1.y + cx * n.y + cy * bitan.y); positions.Add(p1.z + cx * n.z + cy * bitan.z); uvs.Add(i / radialSegments); uvs.Add(j / tubularSegments); } } for (var i = 0; i < radialSegments; i++) { for (var j = 0; j < tubularSegments; j++) { var jNext = (j + 1) % tubularSegments; var a = i * tubularSegments + j; var b = (i + 1) * tubularSegments + j; var c = (i + 1) * tubularSegments + jNext; var d = i * tubularSegments + jNext; indices.Add(d); indices.Add(b); indices.Add(a); indices.Add(d); indices.Add(c); indices.Add(b); } } ComputeNormals(positions, indices, normals); var vertexData = new VertexData(); vertexData.indices = indices; vertexData.positions = positions; vertexData.normals = normals; vertexData.uvs = uvs; return(vertexData); }
public override VertexData _regenerateVertexData() { return(VertexData.CreateTorusKnot(this.radius, this.tube, this.radialSegments, this.tubularSegments, this.p, this.q)); }
/// <summary> /// </summary> /// <param name="height"> /// </param> /// <param name="diameterTop"> /// </param> /// <param name="diameterBottom"> /// </param> /// <param name="tessellation"> /// </param> /// <param name="subdivisions"> /// </param> /// <returns> /// </returns> public static VertexData CreateCylinder( double height = 1.0, double diameterTop = 0.5, double diameterBottom = 1.0, int tessellation = 16, int subdivisions = 1) { var radiusTop = diameterTop / 2; var radiusBottom = diameterBottom / 2; var indices = new Array <int>(); var positions = new Array <double>(); var normals = new Array <double>(); var uvs = new Array <double>(); subdivisions = (subdivisions < 1) ? 1 : subdivisions; var getCircleVector = new Func <int, Vector3>( (i) => { var angle = i * 2.0 * Math.PI / tessellation; var dx = Math.Cos(angle); var dz = Math.Sin(angle); return(new Vector3(dx, 0, dz)); }); Vector3 offset; var createCylinderCap = new Action <bool>( (isTop) => { var radius = isTop ? radiusTop : radiusBottom; if (radius == 0.0) { return; } var vbase = positions.Length / 3; offset = new Vector3(0, height / 2, 0); var textureScale = new Vector2(0.5, 0.5); if (!isTop) { offset.scaleInPlace(-1.0); textureScale.x = -textureScale.x; } for (var i = 0; i < tessellation; i++) { var circleVector = getCircleVector(i); var position = circleVector.scale(radius).add(offset); var textureCoordinate = new Vector2(circleVector.x * textureScale.x + 0.5, circleVector.z * textureScale.y + 0.5); positions.Add(position.x, position.y, position.z); uvs.Add(textureCoordinate.x, textureCoordinate.y); } for (var i = 0; i < tessellation - 2; i++) { if (!isTop) { indices.Add(vbase); indices.Add(vbase + (i + 2) % tessellation); indices.Add(vbase + (i + 1) % tessellation); } else { indices.Add(vbase); indices.Add(vbase + (i + 1) % tessellation); indices.Add(vbase + (i + 2) % tessellation); } } }); var _base = new Vector3(0, -1, 0).scale(height / 2); offset = new Vector3(0, 1, 0).scale(height / subdivisions); var stride = tessellation + 1; for (var i = 0; i <= tessellation; i++) { var circleVector = getCircleVector(i); var textureCoordinate = new Vector2(i / tessellation, 0); var radius = radiusBottom; for (var s = 0; s <= subdivisions; s++) { var position = circleVector.scale(radius); position.addInPlace(_base.add(offset.scale(s))); textureCoordinate.y += 1 / subdivisions; radius += (radiusTop - radiusBottom) / subdivisions; positions.Add(position.x, position.y, position.z); uvs.Add(textureCoordinate.x, textureCoordinate.y); } } subdivisions += 1; for (var s = 0; s < subdivisions - 1; s++) { for (var i = 0; i <= tessellation; i++) { indices.Add(i * subdivisions + s); indices.Add((i * subdivisions + (s + subdivisions)) % (stride * subdivisions)); indices.Add(i * subdivisions + (s + 1)); indices.Add(i * subdivisions + (s + 1)); indices.Add((i * subdivisions + (s + subdivisions)) % (stride * subdivisions)); indices.Add((i * subdivisions + (s + subdivisions + 1)) % (stride * subdivisions)); } } createCylinderCap(true); createCylinderCap(false); ComputeNormals(positions, indices, normals); var vertexData = new VertexData(); vertexData.indices = indices; vertexData.positions = positions; vertexData.normals = normals; vertexData.uvs = uvs; return(vertexData); }
public Plane(int id, Scene scene, double size, bool canBeRegenerated = false, Mesh mesh = null) : base(id, scene, VertexData.CreatePlane(size), canBeRegenerated, mesh) { this.size = size; }
public override VertexData _regenerateVertexData() { return(VertexData.CreatePlane(this.size)); }
public override VertexData _regenerateVertexData() { return(VertexData.CreateGround(this.width, this.height, this.subdivisions)); }
public override VertexData _regenerateVertexData() { return(VertexData.CreateTiledGround(this.xmin, this.zmin, this.xmax, this.zmax, this.subdivisions, this.precision)); }
public override VertexData _regenerateVertexData() { return(VertexData.CreateTorus(this.diameter, this.thickness, this.tessellation)); }
public override VertexData _regenerateVertexData() { return(VertexData.CreateCylinder(this.height, this.diameterTop, this.diameterBottom, this.tessellation, this.subdivisions)); }
public override VertexData _regenerateVertexData() { return(VertexData.CreateSphere(this.segments, this.diameter)); }
public Sphere(int id, Scene scene, int segments, double diameter, bool canBeRegenerated = false, Mesh mesh = null) : base(id, scene, VertexData.CreateSphere(segments, diameter), canBeRegenerated, mesh) { this.segments = segments; this.diameter = diameter; }
/// <summary> /// </summary> /// <param name="vertexData"> /// </param> /// <param name="updatable"> /// </param> public virtual void setAllVerticesData(VertexData vertexData, bool updatable = false) { vertexData.applyToGeometry(this, updatable); }