private static void drawHeightfield(HeightFieldShape heightFieldShape, GraphicsDevice device) { VertexPositionNormalTexture[] cubeVertices; VertexDeclaration basicEffectVertexDeclaration; VertexBuffer vertexBuffer; var white = new Color(1, 1, 1, 1); int vertexNum = (heightFieldShape.HeightField.NumberOfRows - 1) * (heightFieldShape.HeightField.NumberOfColumns - 1) * 3 * 2; var vertices = new VertexPositionColor[vertexNum]; int triangleIndex; Vector3 pos; int vertexIndex = 0; HeightFieldShape.GetTriangleResult triangle; Camera _camera = CamerasManager.Instance.GetActiveCamera(); for (int row = 0; row < heightFieldShape.HeightField.NumberOfRows - 1; row++) { for (int column = 0; column < heightFieldShape.HeightField.NumberOfColumns - 1; column++) { triangleIndex = 2 * (row * heightFieldShape.HeightField.NumberOfColumns + column); triangle = heightFieldShape.GetTriangle(triangleIndex); pos = new Vector3(triangle.WorldTriangle.Vertex2.X, triangle.WorldTriangle.Vertex2.Y, triangle.WorldTriangle.Vertex2.Z); vertices[vertexIndex++] = new VertexPositionColor(pos, white); pos = new Vector3(triangle.WorldTriangle.Vertex1.X, triangle.WorldTriangle.Vertex1.Y, triangle.WorldTriangle.Vertex1.Z); vertices[vertexIndex++] = new VertexPositionColor(pos, white); pos = new Vector3(triangle.WorldTriangle.Vertex0.X, triangle.WorldTriangle.Vertex0.Y, triangle.WorldTriangle.Vertex0.Z); vertices[vertexIndex++] = new VertexPositionColor(pos, white); triangleIndex++; triangle = heightFieldShape.GetTriangle(triangleIndex); pos = new Vector3(triangle.WorldTriangle.Vertex2.X, triangle.WorldTriangle.Vertex2.Y, triangle.WorldTriangle.Vertex2.Z); vertices[vertexIndex++] = new VertexPositionColor(pos, white); pos = new Vector3(triangle.WorldTriangle.Vertex1.X, triangle.WorldTriangle.Vertex1.Y, triangle.WorldTriangle.Vertex1.Z); vertices[vertexIndex++] = new VertexPositionColor(pos, white); pos = new Vector3(triangle.WorldTriangle.Vertex0.X, triangle.WorldTriangle.Vertex0.Y, triangle.WorldTriangle.Vertex0.Z); vertices[vertexIndex++] = new VertexPositionColor(pos, white); } } //inicio do código do cubo //InitializeCube(); basicEffectVertexDeclaration = new VertexDeclaration( device, VertexPositionNormalTexture.VertexElements); var basicEffect = new BasicEffect(device, null); basicEffect.Alpha = 1.0f; basicEffect.DiffuseColor = new Vector3(0.2f, 0.0f, 1.0f); basicEffect.SpecularColor = new Vector3(0.25f, 0.25f, 0.25f); basicEffect.SpecularPower = 5.0f; basicEffect.AmbientLightColor = new Vector3(0.75f, 0.75f, 0.75f); //basicEffect.DirectionalLight0.Enabled = true; //basicEffect.DirectionalLight0.DiffuseColor = Vector3.One; //basicEffect.DirectionalLight0.Direction = Vector3.Normalize(new Vector3(1.0f, -1.0f, -1.0f)); //basicEffect.DirectionalLight0.SpecularColor = Vector3.One; //basicEffect.DirectionalLight1.Enabled = true; //basicEffect.DirectionalLight1.DiffuseColor = new Vector3(0.5f, 0.5f, 0.5f); //basicEffect.DirectionalLight1.Direction = Vector3.Normalize(new Vector3(-1.0f, -1.0f, 1.0f)); //basicEffect.DirectionalLight1.SpecularColor = new Vector3(0.5f, 0.5f, 0.5f); //basicEffect.LightingEnabled = true; basicEffect.World = Matrix.CreateScale(1, 1, 1); basicEffect.View = _camera.View; basicEffect.Projection = _camera.Projection; //NoNameEngine.Instance.Device.Clear(Color.SteelBlue); //NoNameEngine.Instance.Device.RenderState.CullMode = CullMode.CullClockwiseFace; device.VertexDeclaration = basicEffectVertexDeclaration; vertexBuffer = new VertexBuffer( device, VertexPositionColor.SizeInBytes * vertexNum, BufferUsage.None ); vertexBuffer.SetData(vertices); device.Vertices[0].SetSource(vertexBuffer, 0, VertexPositionColor.SizeInBytes); // This code would go between a NoNameEngine.Instance.Device // BeginScene-EndScene block. basicEffect.Begin(); foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes) { pass.Begin(); //this.NoNameEngine.Instance.Device.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleList, vertices, 0, vertexNum / 3); device.DrawPrimitives( PrimitiveType.TriangleList, 0, vertexNum / 3 ); //NoNameEngine.Instance.Device.DrawPrimitives( // PrimitiveType.TriangleList, // 0, // 12 // ); pass.End(); } basicEffect.End(); }
private void CreateDecalForStaticObject(ShapeTriangleID startTriangle, Vec3 pos, Vec3 normal, MapObject parentMapObject) { bool existsNormalsMore45Degrees = false; //find near triangles //Set<ShapeTriangleID> triangleIDs = new Set<ShapeTriangleID>(); { Sphere checkSphere = new Sphere(pos, Type.Size * .5f * 1.41f);//Sqrt(2) //Set<ShapeTriangleID> checkedTriangles = new Set<ShapeTriangleID>(); //Stack<ShapeTriangleID> trianglesForCheck = new Stack<ShapeTriangleID>( 16 ); trianglesForCheck.Push(startTriangle); while (trianglesForCheck.Count != 0) { ShapeTriangleID triangle = trianglesForCheck.Pop(); //add to checked triangles if (!checkedTriangles.AddWithCheckAlreadyContained(triangle)) { //ignore already checked triangles continue; } //get triangle points Vec3 p0, p1, p2; { switch (triangle.shape.ShapeType) { case Shape.Type.Mesh: MeshShape meshShape = (MeshShape)triangle.shape; meshShape.GetTriangle(triangle.triangleID, true, out p0, out p1, out p2); break; case Shape.Type.HeightField: HeightFieldShape heightFieldShape = (HeightFieldShape)triangle.shape; heightFieldShape.GetTriangle(triangle.triangleID, true, out p0, out p1, out p2); break; default: Log.Fatal("DecalCreator: CreateDecalForStaticObject: Not supported shape type ({0}).", triangle.shape.ShapeType); return; } } //cull by checkBounds if (!checkSphere.TriangleIntersection(p0, p1, p2)) { continue; } //check normal bool correctNormal = false; if (Type.SpreadType != DecalCreatorType.SpreadTypes.Directional) { Plane plane = Plane.FromPoints(p0, p1, p2); if (plane.GetSide(pos + normal) == Plane.Side.Positive) { Radian angle = MathFunctions.ACos(Vec3.Dot(normal, plane.Normal)); if (angle <= new Degree(70.0f).InRadians()) { if (!existsNormalsMore45Degrees && angle >= new Degree(45.0f).InRadians()) { existsNormalsMore45Degrees = true; } correctNormal = true; } } } else { correctNormal = true; } if (correctNormal) { //add triangle to result list triangleIDs.Add(triangle); } //add near triangles to check list { //expand vertices const float border = .001f; Vec3 center = (p0 + p1 + p2) * (1.0f / 3.0f); Vec3 diff0 = p0 - center; Vec3 diff1 = p1 - center; Vec3 diff2 = p2 - center; if (diff0 != Vec3.Zero && diff1 != Vec3.Zero && diff2 != Vec3.Zero) { p0 += diff0.GetNormalize() * border; p1 += diff1.GetNormalize() * border; p2 += diff2.GetNormalize() * border; Vec3 p01 = (p0 + p1) * .5f; Vec3 p12 = (p1 + p2) * .5f; Vec3 p20 = (p2 + p0) * .5f; //find triangles for (int n = 0; n < 3; n++) { Vec3 p = Vec3.Zero; switch (n) { case 0: p = p01; break; case 1: p = p12; break; case 2: p = p20; break; } RayCastResult[] piercingResult = PhysicsWorld.Instance.RayCastPiercing(new Ray( p + normal * .025f, -normal * .05f), (int)ContactGroup.CastOnlyCollision); foreach (RayCastResult result in piercingResult) { if (result.Shape != null) { trianglesForCheck.Push(new ShapeTriangleID( result.Shape, result.TriangleID)); } } } } } } checkedTriangles.Clear(); } if (triangleIDs.Count == 0) { return; } //calculate perpendiculars to normal Vec3 side1Normal; Vec3 side2Normal; { if (Math.Abs(normal.X) > .001f || Math.Abs(normal.Y) > .001f) { side1Normal = Mat3.FromRotateByZ(MathFunctions.PI / 2) * new Vec3(normal.X, normal.Y, 0); side1Normal.Normalize(); } else { side1Normal = new Vec3(1, 0, 0); } side2Normal = Vec3.Cross(normal, side1Normal); } //generate clip planes Plane[] clipPlanes = new Plane[6]; { float halfSize = Type.Size * .5f; if (existsNormalsMore45Degrees) { halfSize *= 1.41f; } Plane p; p = Plane.FromVectors(normal, -side2Normal, Position); clipPlanes[0] = new Plane(p.Normal, p.Distance + halfSize); p = Plane.FromVectors(normal, side2Normal, Position); clipPlanes[1] = new Plane(p.Normal, p.Distance + halfSize); p = Plane.FromVectors(normal, -side1Normal, Position); clipPlanes[2] = new Plane(p.Normal, p.Distance + halfSize); p = Plane.FromVectors(normal, side1Normal, Position); clipPlanes[3] = new Plane(p.Normal, p.Distance + halfSize); p = Plane.FromVectors(side1Normal, side2Normal, Position); clipPlanes[4] = new Plane(p.Normal, p.Distance + halfSize); //clipPlanes[ 4 ] = new Plane( p.Normal, p.Distance + halfSize * .5f ); p = Plane.FromVectors(side1Normal, -side2Normal, Position); clipPlanes[5] = new Plane(p.Normal, p.Distance + halfSize); //clipPlanes[ 5 ] = new Plane( p.Normal, p.Distance + halfSize * .5f ); } //generate vertices and indices by triangles //List<Decal.Vertex> vertices = new List<Decal.Vertex>( triangleIDs.Count * 3 ); //List<int> indices = new List<int>( triangleIDs.Count * 3 ); List <Decal.Vertex> vertices = tempVertices; List <int> indices = tempIndices; vertices.Clear(); indices.Clear(); { foreach (ShapeTriangleID triangle in triangleIDs) { Vec3 p0, p1, p2; { switch (triangle.shape.ShapeType) { case Shape.Type.Mesh: MeshShape meshShape = (MeshShape)triangle.shape; meshShape.GetTriangle(triangle.triangleID, true, out p0, out p1, out p2); break; case Shape.Type.HeightField: HeightFieldShape heightFieldShape = (HeightFieldShape)triangle.shape; heightFieldShape.GetTriangle(triangle.triangleID, true, out p0, out p1, out p2); break; default: Log.Fatal("DecalCreator: CreateDecalForStaticObject: Not supported shape type ({0}).", triangle.shape.ShapeType); return; } } List <Vec3> list = new List <Vec3>(); list.Add(p0); list.Add(p1); list.Add(p2); //clip by planes foreach (Plane plane in clipPlanes) { list = CutConvexPlanePolygonByPlane(list, plane); if (list == null) { break; } } //add to vertices and indices lists if (list != null) { int vertexCount = vertices.Count; Vec3 norm = Plane.FromPoints(p0, p1, p2).Normal; foreach (Vec3 p in list) { vertices.Add(new Decal.Vertex(p, norm, Vec2.Zero, Vec3.Zero)); } for (int n = 1; n < list.Count - 1; n++) { indices.Add(vertexCount); indices.Add(vertexCount + n); indices.Add(vertexCount + n + 1); } } } } triangleIDs.Clear(); if (indices.Count == 0) { return; } //calculate texCoord and Type.DepthRenderOffset { Plane planeSide1 = Plane.FromVectors(normal, side1Normal, Position); Plane planeSide2 = Plane.FromVectors(normal, side2Normal, Position); float invSize = 1.0f / Type.Size; for (int n = 0; n < vertices.Count; n++) { Decal.Vertex vertex = vertices[n]; //calculate texCoord float distance1 = planeSide1.GetDistance(vertex.position); float distance2 = planeSide2.GetDistance(vertex.position); vertex.texCoord = new Vec2(distance1 * invSize + .5f, distance2 * invSize + .5f); //Add perpendicular to normal offset. //Alternative way: for shader based rendering use DepthOffset property of decal material. //if( !RenderSystem.Instance.HasShaderModel3() ) { //add Type.DepthRenderOffset vertex.position = vertex.position + normal * Type.DepthRenderOffset; } vertices[n] = vertex; } } //calculate tangent vectors { int triangleCount = indices.Count / 3; for (int nTriangle = 0; nTriangle < triangleCount; nTriangle++) { int index0 = indices[nTriangle * 3 + 0]; int index1 = indices[nTriangle * 3 + 1]; int index2 = indices[nTriangle * 3 + 2]; Decal.Vertex vertex0 = vertices[index0]; Decal.Vertex vertex1 = vertices[index1]; Decal.Vertex vertex2 = vertices[index2]; Vec3 tangent = MathUtils.CalculateTangentSpaceVector( vertex0.position, vertex0.texCoord, vertex1.position, vertex1.texCoord, vertex2.position, vertex2.texCoord); vertex0.tangent += tangent; vertex1.tangent += tangent; vertex2.tangent += tangent; vertices[index0] = vertex0; vertices[index1] = vertex1; vertices[index2] = vertex2; } for (int n = 0; n < vertices.Count; n++) { Decal.Vertex vertex = vertices[n]; if (vertex.tangent != Vec3.Zero) { vertex.tangent.Normalize(); } vertices[n] = vertex; } } //subtract decal position (make local vertices coordinates) { for (int n = 0; n < vertices.Count; n++) { Decal.Vertex vertex = vertices[n]; vertex.position -= Position; vertices[n] = vertex; } } //get material string materialName = null; { string physicsMaterialName = startTriangle.shape.MaterialName; string defaultMaterialName = ""; foreach (DecalCreatorType.MaterialItem item in Type.Materials) { if (item.PhysicsMaterialName == physicsMaterialName) { materialName = item.MaterialName; } if (string.IsNullOrEmpty(item.PhysicsMaterialName)) { defaultMaterialName = item.MaterialName; } } if (materialName == null) { materialName = defaultMaterialName; } } //create Decal Decal decal = (Decal)Entities.Instance.Create("Decal", Map.Instance); decal.Position = Position; decal.Init(this, vertices.ToArray(), indices.ToArray(), materialName, parentMapObject); decal.PostCreate(); Type.AddDecalToCreatedList(decal); decals.Add(decal); }