private static IExplicitModel BuildWallModel(List <BuildingWallSegment> wallSegments) { var vertices = new VertexPosTanNormTex[wallSegments.Count * 4]; var indices = new int[wallSegments.Count * 6]; for (int i = 0; i < wallSegments.Count; i++) { var segment = wallSegments[i].Basement; var height = wallSegments[i].Height; var vertexOffset = i * 4; var indexOffset = i * 6; var tangent = (segment.Point2 - segment.Point1).Normalize(); var normal = Vector3.Cross(tangent, Vector3.UnitY).Normalize(); var texCoordWidth = Math.Max((float)Math.Round(segment.Length / 2), 1f); var texCoordHeight = Math.Max((float)Math.Round(height / 2), 1f); vertices[vertexOffset + 0] = new VertexPosTanNormTex(segment.Point1, tangent, normal, new Vector2(0, texCoordHeight)); vertices[vertexOffset + 1] = new VertexPosTanNormTex(segment.Point1 + height * Vector3.UnitY, tangent, normal, new Vector2(0, 0)); vertices[vertexOffset + 2] = new VertexPosTanNormTex(segment.Point2 + height * Vector3.UnitY, tangent, normal, new Vector2(texCoordWidth, 0)); vertices[vertexOffset + 3] = new VertexPosTanNormTex(segment.Point2, tangent, normal, new Vector2(texCoordWidth, texCoordHeight)); indices[indexOffset + 0] = vertexOffset; indices[indexOffset + 1] = vertexOffset + 1; indices[indexOffset + 2] = vertexOffset + 2; indices[indexOffset + 3] = vertexOffset; indices[indexOffset + 4] = vertexOffset + 2; indices[indexOffset + 5] = vertexOffset + 3; } return(ExplicitModel.FromVertices(vertices, indices, ExplicitModelPrimitiveTopology.TriangleList)); }
public override IResource GetNew(IResourceSource resourceSource) { var cSource = (Source)resourceSource; var verticalIndexOffset = 2 * cSource.HalfNumCircleSegments; var vertices = new VertexPosTanNormTex[verticalIndexOffset * cSource.HalfNumCircleSegments]; for (int i = 0; i < cSource.HalfNumCircleSegments; i++) { for (int j = 0; j < verticalIndexOffset; j++) { var u = (float)j / (verticalIndexOffset - 1); var v = (float)i / (cSource.HalfNumCircleSegments - 1); var phi = MathHelper.TwoPi * u + MathHelper.Pi; var psi = MathHelper.PiOver2 - MathHelper.Pi * v; var z = MathHelper.Cos(phi) * MathHelper.Cos(psi); var x = MathHelper.Sin(phi) * MathHelper.Cos(psi); var y = MathHelper.Sin(psi); var normal = new Vector3(x, y, z); var position = normal; var tangent = Vector3.Cross(Vector3.UnitY, normal).Normalize(); var texcoord = new Vector2(u, v); vertices[i * verticalIndexOffset + j] = new VertexPosTanNormTex( position, tangent, normal, texcoord); } } var indexList = new List <int>(); for (int i = 0; i < cSource.HalfNumCircleSegments - 1; i++) { for (int j = 0; j < verticalIndexOffset - 1; j++) { var topLeftIndex = i * verticalIndexOffset + j; indexList.Add(topLeftIndex); indexList.Add(topLeftIndex + 1); indexList.Add(topLeftIndex + 1 + verticalIndexOffset); indexList.Add(topLeftIndex); indexList.Add(topLeftIndex + 1 + verticalIndexOffset); indexList.Add(topLeftIndex + verticalIndexOffset); } } var indices = indexList.ToArray(); if (cSource.Inverse) { for (int i = 0; i < vertices.Length; i++) { vertices[i].Normal = -vertices[i].Normal; } for (int i = 0; i < indices.Length; i += 3) { CodingHelper.Swap(ref indices[i + 1], ref indices[i + 2]); } } return(ExplicitModel.FromVertices(vertices, indices, ExplicitModelPrimitiveTopology.TriangleList).WithSource(cSource)); }
public unsafe GlObjects GetGlObjects() { if (!dirty) { return(glObjects); } if (glObjects.Vao == null) { glObjects.Vao = infra.GlContext.Create.VertexArray(); } glObjects.Vao.DisableVertexAttributesStartingFrom(0); var bufferUsageHint = model.Volatility == ResourceVolatility.Volatile ? BufferUsageHint.DynamicRead : BufferUsageHint.StaticRead; // todo: other formats var vertices = new VertexPosTanNormTex[model.Positions.Length]; var getTangent = model.Tangents != null ? (Func <IExplicitModel, int, Vector3>)((m, i) => m.Tangents[i]) : (m, i) => Vector3.Zero; var getNormal = model.Normals != null ? (Func <IExplicitModel, int, Vector3>)((m, i) => m.Normals[i]) : (m, i) => Vector3.Zero; var getTexCoord = model.TexCoords != null ? (Func <IExplicitModel, int, Vector2>)((m, i) => m.TexCoords[i]) : (m, i) => Vector2.Zero; for (var i = 0; i < vertices.Length; i++) { vertices[i] = new VertexPosTanNormTex(model.Positions[i], getTangent(model, i), getNormal(model, i), getTexCoord(model, i)); } var vertexBufferSize = vertices.Length * VertexPosTanNormTex.SizeInBytes; if (glObjects.VertexBuffer == null || glObjects.VertexBuffer.SizeInBytes != vertexBufferSize) { glObjects.VertexBuffer?.Dispose(); glObjects.VertexBuffer = infra.GlContext.Create.Buffer(BufferTarget.Array, vertexBufferSize, bufferUsageHint); } fixed(VertexPosTanNormTex *pVertices = vertices) glObjects.VertexBuffer.SetData((IntPtr)pVertices); var elemInfos = VertexPosTanNormTex.GetElementsInfos(0); var positionInfo = elemInfos.Single(x => x.CommonSemantic == CommonVertexSemantic.Position); var normalInfo = elemInfos.Single(x => x.CommonSemantic == CommonVertexSemantic.Normal); var tangentInfo = elemInfos.Single(x => x.CommonSemantic == CommonVertexSemantic.Tangent); var texCoordInfo = elemInfos.Single(x => x.CommonSemantic == CommonVertexSemantic.TexCoord); glObjects.Vao.SetVertexAttributeF(0, glObjects.VertexBuffer, VertexAttributeDimension.Three, VertexAttribPointerType.Float, false, positionInfo.Stride, positionInfo.Offset); glObjects.Vao.SetVertexAttributeF(1, glObjects.VertexBuffer, VertexAttributeDimension.Three, VertexAttribPointerType.Float, false, normalInfo.Stride, normalInfo.Offset); glObjects.Vao.SetVertexAttributeF(2, glObjects.VertexBuffer, VertexAttributeDimension.Two, VertexAttribPointerType.Float, false, texCoordInfo.Stride, texCoordInfo.Offset); glObjects.Vao.SetVertexAttributeF(3, glObjects.VertexBuffer, VertexAttributeDimension.Three, VertexAttribPointerType.Float, false, tangentInfo.Stride, tangentInfo.Offset); if (!model.IndicesAreTrivial) { glObjects.SixteenBitIndices = model.MinIndexSize < sizeof(int); var indexSize = glObjects.SixteenBitIndices ? sizeof(ushort) : sizeof(int); var indexBufferSize = model.Indices.Length * indexSize; if (glObjects.IndexBuffer == null || glObjects.IndexBuffer.SizeInBytes != indexBufferSize) { glObjects.Vao.SetElementArrayBuffer(null); glObjects.IndexBuffer?.Dispose(); glObjects.IndexBuffer = infra.GlContext.Create.Buffer(BufferTarget.ElementArray, indexBufferSize, bufferUsageHint); } if (glObjects.SixteenBitIndices) { var indices = model.Indices.Select(x => (ushort)x).ToArray(); fixed(ushort *pIndices = indices) glObjects.IndexBuffer.SetData((IntPtr)pIndices); } else { fixed(int *pIndices = model.Indices) glObjects.IndexBuffer.SetData((IntPtr)pIndices); } glObjects.Vao.SetElementArrayBuffer(glObjects.IndexBuffer); } else { glObjects.Vao.SetElementArrayBuffer(null); glObjects.IndexBuffer?.Dispose(); glObjects.IndexBuffer = null; } dirty = false; return(glObjects); }