private static void InitNormals(ref TerrainMapComponent terrain) { int indicesLen = terrain.indices.Length / 3; for (int i = 0; i < terrain.vertices.Length; ++i) { terrain.vertices[i].Normal = new Vector3(0f, 0f, 0f); } for (int i = 0; i < indicesLen; ++i) { //get indices indexes int i1 = terrain.indices[i * 3]; int i2 = terrain.indices[i * 3 + 1]; int i3 = terrain.indices[i * 3 + 2]; //get the two faces Vector3 face1 = terrain.vertices[i1].Position - terrain.vertices[i3].Position; Vector3 face2 = terrain.vertices[i1].Position - terrain.vertices[i2].Position; //get the cross product between them Vector3 normal = Vector3.Cross(face1, face2); //update the normal terrain.vertices[i1].Normal += normal; terrain.vertices[i2].Normal += normal; terrain.vertices[i3].Normal += normal; } }
public static void LoadHeightMap(ref TerrainMapComponent terrain, Texture2D terrainMap, Texture2D defaultTex, GraphicsDevice graphicsDevice) { terrain.terrainMap = terrainMap; int width = terrainMap.Width; int height = terrainMap.Height; //get the pixels from the terrain map Color[] colors = new Color[width * height]; terrainMap.GetData(colors); terrain.heightInfo = new float[width, height]; for (int x = 0; x < width; ++x) { for (int y = 0; y < height; ++y) { terrain.heightInfo[x, y] = colors[x + y * width].R / 5f; } } terrain.vertices = InitTerrainVertices(terrain.heightInfo, width, height); terrain.indices = InitIndices(width, height); InitNormals(ref terrain); //setup the terrain chunks SetupTerrainChunks(ref terrain, graphicsDevice, defaultTex); }
/// <summary> /// This method adds the static models to the chunks they stand upon /// </summary> public static void AddStaticModelsToChunks() { Entity e = ComponentManager.Instance.GetFirstEntityOfType <TerrainMapComponent>(); if (e == null) { return; } TerrainMapComponent terrainComponent = ComponentManager.Instance.GetEntityComponent <TerrainMapComponent>(e); TransformComponent transformComponent = ComponentManager.Instance.GetEntityComponent <TransformComponent>(e); List <Entity> entModels = ComponentManager.Instance.GetAllEntitiesWithComponentType <ModelComponent>(); if (entModels == null) { return; } for (int i = 0; i < terrainComponent.terrainChunks.Count; ++i) { Matrix world = Matrix.CreateTranslation(terrainComponent.terrainChunks[i].offsetPosition); //get the bounding box for the terrain chunk BoundingBox box = boxConvert.ConvertBoundingBoxToWorldCoords(terrainComponent.terrainChunks[i].boundingBox, world); for (int j = 0; j < entModels.Count; j++) { TransformComponent tComp = ComponentManager.Instance.GetEntityComponent <TransformComponent>(entModels[j]); ModelBoundingSphereComponent spComp = ComponentManager.Instance.GetEntityComponent <ModelBoundingSphereComponent>(entModels[j]); ModelComponent mComp = ComponentManager.Instance.GetEntityComponent <ModelComponent>(entModels[j]); //If there is a transformcomponent if (tComp != null) { BoundingSphere newSphere; //and a sphere component if (spComp != null) { newSphere = sphereConvert.ConvertBoundingSphereToWorldCoords(spComp.sphere, tComp.World); //if the box and the sphere overlaps if (box.Intersects(newSphere)) { //if it's a static model if (mComp.staticModel.Equals(true)) { //add the entity to the chunk terrainComponent.terrainChunks[i].staticModels.Add(entModels[j]); } } } } } } }
private void InitTerrain(ECSEngine engine) { _sm.RegisterSystem("Game", new TerrainMapRenderSystem()); var terrainTex = engine.LoadContent <Texture2D>("Canyon"); var defaultTex = engine.LoadContent <Texture2D>("grasstile"); var terrain = EntityFactory.Instance.NewEntityWithTag("Terrain"); var t = new TerrainMapComponent(engine.GetGraphicsDevice(), terrainTex, defaultTex, 10); var tf = new TransformComponent(); TerrainMapRenderSystem.LoadHeightMap(ref t, terrainTex, defaultTex, engine.GetGraphicsDevice()); t.SetTextureToChunk(0, engine.LoadContent <Texture2D>("LTCornerroad")); t.SetTextureToChunk(1, engine.LoadContent <Texture2D>("verticalroad")); t.SetTextureToChunk(2, engine.LoadContent <Texture2D>("verticalroad")); t.SetTextureToChunk(3, engine.LoadContent <Texture2D>("verticalroad")); t.SetTextureToChunk(4, engine.LoadContent <Texture2D>("verticalroad")); t.SetTextureToChunk(5, engine.LoadContent <Texture2D>("verticalroad")); t.SetTextureToChunk(6, engine.LoadContent <Texture2D>("verticalroad")); t.SetTextureToChunk(7, engine.LoadContent <Texture2D>("verticalroad")); t.SetTextureToChunk(8, engine.LoadContent <Texture2D>("verticalroad")); t.SetTextureToChunk(9, engine.LoadContent <Texture2D>("LBCornerroad")); t.SetTextureToChunk(10, engine.LoadContent <Texture2D>("horizontalroad")); t.SetTextureToChunk(19, engine.LoadContent <Texture2D>("horizontalroad")); t.SetTextureToChunk(20, engine.LoadContent <Texture2D>("horizontalroad")); t.SetTextureToChunk(29, engine.LoadContent <Texture2D>("horizontalroad")); t.SetTextureToChunk(30, engine.LoadContent <Texture2D>("horizontalroad")); t.SetTextureToChunk(39, engine.LoadContent <Texture2D>("horizontalroad")); t.SetTextureToChunk(40, engine.LoadContent <Texture2D>("horizontalroad")); t.SetTextureToChunk(49, engine.LoadContent <Texture2D>("horizontalroad")); t.SetTextureToChunk(50, engine.LoadContent <Texture2D>("horizontalroad")); t.SetTextureToChunk(59, engine.LoadContent <Texture2D>("horizontalroad")); t.SetTextureToChunk(60, engine.LoadContent <Texture2D>("horizontalroad")); t.SetTextureToChunk(69, engine.LoadContent <Texture2D>("horizontalroad")); t.SetTextureToChunk(70, engine.LoadContent <Texture2D>("horizontalroad")); t.SetTextureToChunk(79, engine.LoadContent <Texture2D>("horizontalroad")); t.SetTextureToChunk(80, engine.LoadContent <Texture2D>("horizontalroad")); t.SetTextureToChunk(89, engine.LoadContent <Texture2D>("horizontalroad")); t.SetTextureToChunk(90, engine.LoadContent <Texture2D>("RTCornerroad")); t.SetTextureToChunk(99, engine.LoadContent <Texture2D>("RBCornerroad")); t.SetTextureToChunk(98, engine.LoadContent <Texture2D>("verticalroad")); t.SetTextureToChunk(97, engine.LoadContent <Texture2D>("verticalroad")); t.SetTextureToChunk(96, engine.LoadContent <Texture2D>("verticalroad")); t.SetTextureToChunk(95, engine.LoadContent <Texture2D>("verticalroad")); t.SetTextureToChunk(94, engine.LoadContent <Texture2D>("verticalroad")); t.SetTextureToChunk(93, engine.LoadContent <Texture2D>("verticalroad")); t.SetTextureToChunk(92, engine.LoadContent <Texture2D>("verticalroad")); t.SetTextureToChunk(91, engine.LoadContent <Texture2D>("verticalroad")); tf.World = Matrix.CreateTranslation(0, 0, 0); tf.Position = Vector3.Zero; ComponentManager.Instance.AddComponentToEntity(terrain, t); ComponentManager.Instance.AddComponentToEntity(terrain, tf); SceneManager.Instance.AddEntityToSceneOnLayer("Game", 2, terrain); }
private static VertexPositionNormalTexture[] GetVertexTextureNormals(TerrainMapComponent terrain, Rectangle rect) { VertexPositionNormalTexture[] terrainVerts = new VertexPositionNormalTexture[rect.Width * rect.Height]; for (int x = rect.X; x < rect.X + rect.Width; x++) { for (int y = rect.Y; y < rect.Y + rect.Height; y++) { terrainVerts[(x - rect.X) + (y - rect.Y) * rect.Height].Normal = terrain.vertices[x + y * terrain.hmHeight].Normal; } } return(terrainVerts); }
public static float GetTerrainHeight(TerrainMapComponent terrain, float x, float z) { if (terrain == null) { return(10); } if (x < 0 || z < 0 || x > terrain.heightInfo.GetLength(0) - 1 || z > terrain.heightInfo.GetLength(1) - 1) { return(10f); } //find the two x vertices int xLow = (int)x; int xHigh = xLow + 1; //get the relative x value between the two points float xRel = (x - xLow) / ((float)xHigh - (float)xLow); //find the two z verticies int zLow = (int)z; int zHigh = zLow + 1; //get the relative z value between the two points float zRel = (z - zLow) / ((float)zHigh - (float)zLow); //get the minY and MaxY values from the four vertices float heightLowXLowZ = terrain.heightInfo[xLow, zLow]; float heightLowXHighZ = terrain.heightInfo[xLow, zHigh]; float heightHighXLowZ = terrain.heightInfo[xHigh, zLow]; float heightHighXHighZ = terrain.heightInfo[xHigh, zHigh]; //test if the position is above the low triangle bool posAboveLowTriangle = (xRel + zRel < 1); float resultHeight; if (posAboveLowTriangle) { resultHeight = heightLowXLowZ; resultHeight += zRel * (heightLowXHighZ - heightLowXLowZ); resultHeight += xRel * (heightHighXLowZ - heightLowXLowZ); } else { resultHeight = heightHighXHighZ; resultHeight += (1.0f - zRel) * (heightHighXLowZ - heightHighXHighZ); resultHeight += (1.0f - xRel) * (heightLowXHighZ - heightHighXHighZ); } return(resultHeight); }
private static void SetupTerrainChunks(ref TerrainMapComponent terrain, GraphicsDevice graphicsDevice, Texture2D defaultTexture) { //loop through all the chunks to cut out from the heightmap for (terrain.clipX = 0; terrain.clipX < terrain.hmWidth - 1; terrain.clipX += terrain.clipW) { for (terrain.clipY = 0; terrain.clipY < terrain.hmHeight - 1; terrain.clipY += terrain.clipH) { //use this line to see the chunks (don't use in real game) //TerrainChunk t = new TerrainChunk(graphicsDevice, terrainHeightMap, new Rectangle(clipX, clipY, clipW, clipH ), // new Vector3(clipX, 0, -clipY), GetVertexTextureNormals(new Rectangle(clipX, clipY, clipW , clipH ))); Rectangle clipRect = new Rectangle(terrain.clipX, terrain.clipY, terrain.clipW + 1, terrain.clipH + 1); TerrainChunk t = new TerrainChunk(graphicsDevice, terrain.terrainHeightMap, clipRect, new Vector3(terrain.clipX, 0, -terrain.clipY), GetVertexTextureNormals(terrain, clipRect)); //apply the default texture to the chunk, so that it is visible t.SetTexture(defaultTexture); //add the chunk to the chunklist terrain.terrainChunks.Add(t); } } }
public void Render(GraphicsDevice graphicsDevice, GameTime gameTime) { if (renderBoxInitialised.Equals(false)) { boxConvert = new BoundingBoxToWorldSpace(); boxRenderer = new DebugRenderBoundingBox(graphicsDevice); renderBoxInitialised = true; } Entity e = ComponentManager.Instance.GetFirstEntityOfType <TerrainMapComponent>(); Entity c = ComponentManager.Instance.GetFirstEntityOfType <CameraComponent>(); CameraComponent camera = ComponentManager.Instance.GetEntityComponent <CameraComponent>(c); TerrainMapComponent terrainComponent = ComponentManager.Instance.GetEntityComponent <TerrainMapComponent>(e); TransformComponent transformComponent = ComponentManager.Instance.GetEntityComponent <TransformComponent>(e); if (terrainComponent != null) { if (transformComponent != null) { /*RasterizerState r = new RasterizerState(); * r.CullMode = CullMode.None; * //r.FillMode = FillMode.WireFrame; * graphicsDevice.RasterizerState = r;//*/ terrainComponent.numChunksInView = 0; terrainComponent.numModelsInView = 0; for (int i = 0; i < terrainComponent.terrainChunks.Count; ++i) { terrainComponent.terrainChunks[i].effect.TextureEnabled = true; terrainComponent.terrainChunks[i].effect.VertexColorEnabled = false; terrainComponent.terrainChunks[i].effect.Texture = terrainComponent.terrainChunks[i].terrainTex; terrainComponent.terrainChunks[i].effect.Projection = camera.projectionMatrix; terrainComponent.terrainChunks[i].effect.View = camera.viewMatrix; terrainComponent.terrainChunks[i].effect.World = transformComponent.World * Matrix.CreateTranslation(terrainComponent.terrainChunks[i].offsetPosition); terrainComponent.terrainChunks[i].effect.EnableDefaultLighting(); BoundingBox box = boxConvert.ConvertBoundingBoxToWorldCoords(terrainComponent.terrainChunks[i].boundingBox, terrainComponent.terrainChunks[i].effect.World); if (box.Intersects(camera.cameraFrustrum)) { foreach (EffectPass p in terrainComponent.terrainChunks[i].effect.CurrentTechnique.Passes) { p.Apply(); graphicsDevice.Indices = terrainComponent.terrainChunks[i].iBuffer; graphicsDevice.SetVertexBuffer(terrainComponent.terrainChunks[i].vBuffer); graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, terrainComponent.terrainChunks[0].indicesLenDiv3); } boxRenderer.RenderBoundingBox(terrainComponent.terrainChunks[i].boundingBox, terrainComponent.terrainChunks[i].effect.World, camera.viewMatrix, camera.projectionMatrix); terrainComponent.numChunksInView++; //go through all the entities in the current chunk foreach (Entity staticModelEnt in terrainComponent.terrainChunks[i].staticModels) { //get the transform and modelcomponent TransformComponent tComp = ComponentManager.Instance.GetEntityComponent <TransformComponent>(staticModelEnt); ModelComponent mComp = ComponentManager.Instance.GetEntityComponent <ModelComponent>(staticModelEnt); ModelBoundingSphereComponent sp = ComponentManager.Instance.GetEntityComponent <ModelBoundingSphereComponent>(staticModelEnt); BoundingSphere newSphere = sphereConvert.ConvertBoundingSphereToWorldCoords(sp.sphere, Matrix.CreateTranslation(tComp.Position)); newSphere.Radius += 0.5f; foreach (var pair in mComp.meshTransforms) { //update the model transforms ChangeBoneTransform(mComp, pair.Key, pair.Value); } //if they use the basic effect if (mComp.useBasicEffect) { //and are within the camera frustrum if (camera.cameraFrustrum.Contains(newSphere) != ContainmentType.Disjoint) { terrainComponent.numModelsInView++; //render the model with basic effects modelRenderMethods.RenderBasicEffectModel(mComp, tComp, camera, false); } } } } } } } }
public InitHouses(ECSEngine engine) { Random rnd = new Random(); ModelComponent house = new ModelComponent(engine.LoadContent <Model>("basichouse"), true, true, true); ModelComponent house2 = new ModelComponent(engine.LoadContent <Model>("basichouse"), true, true, true); ModelComponent powerupModel = new ModelComponent(engine.LoadContent <Model>("basichouse"), true, true, false); List <Entity> sceneEntities = SceneManager.Instance.GetActiveScene().GetAllEntities(); Entity terrain = ComponentManager.Instance.GetEntityWithTag("Terrain", sceneEntities); TerrainMapComponent tcomp = ComponentManager.Instance.GetEntityComponent <TerrainMapComponent>(terrain); // Init test-powerup Entity entity = EntityFactory.Instance.NewEntity(); powerupModel.SetTexture(engine.LoadContent <Texture2D>("basichouse_texture1")); powerupModel.textured = true; ComponentManager.Instance.AddComponentToEntity(entity, powerupModel); TransformComponent tt = new TransformComponent(); float hh = (float)rnd.Next(8, 12) / 100; tt.Position = new Vector3(500, 35, -50); tt.Scale = new Vector3(0.08f, hh, 0.08f); ComponentManager.Instance.AddComponentToEntity(entity, tt); ComponentManager.Instance.AddComponentToEntity(entity, new Collision3Dcomponent()); ComponentManager.Instance.AddComponentToEntity(entity, new PowerupModelComponent()); SceneManager.Instance.AddEntityToSceneOnLayer("Game", 1, entity); // Init houses for (int i = 0; i < 1; ++i) { Entity e = EntityFactory.Instance.NewEntity(); if (i < 50) { house.SetTexture(engine.LoadContent <Texture2D>("basichouse_texture1")); house.textured = true; ComponentManager.Instance.AddComponentToEntity(e, house); } else { house2.SetTexture(engine.LoadContent <Texture2D>("basichouse_texture2")); house2.textured = true; ComponentManager.Instance.AddComponentToEntity(e, house2); } TransformComponent t = new TransformComponent(); float minx = rnd.Next(128, 900); float minz = rnd.Next(128, 900); float houseHeight = (float)rnd.Next(8, 12) / 100; t.Position = new Vector3(minx, 0.0f, -minz); t.Position = new Vector3(t.Position.X, TerrainMapRenderSystem.GetTerrainHeight(tcomp, t.Position.X, Math.Abs(t.Position.Z)), t.Position.Z); t.Scale = new Vector3(0.08f, houseHeight, 0.08f); t.World = Matrix.CreateTranslation(t.Position); //house and house2 are identical, so it's ok to use either of them ModelBoundingSphereComponent sphereComp = new ModelBoundingSphereComponent(house, t.Position); ComponentManager.Instance.AddComponentToEntity(e, t); ComponentManager.Instance.AddComponentToEntity(e, sphereComp); ComponentManager.Instance.AddComponentToEntity(e, new Collision3Dcomponent()); SceneManager.Instance.AddEntityToSceneOnLayer("Game", 1, e); } }
public void LockModelToHeight(TerrainMapComponent terComp, TransformComponent trsComp, float offset) { trsComp.Position = new Vector3(trsComp.Position.X, offset + TerrainMapRenderSystem.GetTerrainHeight(terComp, trsComp.Position.X, Math.Abs(trsComp.Position.Z)), trsComp.Position.Z); }
/* Flagges the object as flying if it is above the ground. If it only slightly above the ground * it will still be flagged as non flying to make such detection more responsive. */ public static void TerrainMapCollision(ref TransformComponent trsComp, ref bool airborne, TerrainMapComponent terComp, float groundOffset) { float distanceToGround = -(TerrainMapRenderSystem.GetTerrainHeight(terComp, trsComp.Position.X, Math.Abs(trsComp.Position.Z)) - trsComp.Position.Y); if (distanceToGround <= groundOffset) { trsComp.LockModelToHeight(terComp, groundOffset); trsComp.Velocity.Y = 0; airborne = false; return; } else if (distanceToGround > 10f) { airborne = true; } else { airborne = false; } }