void UpdateView() { target = PlanetEarth.GetPosition(longitude, latitude); Vector3 axis = target; axis.Normalize(); //float sign = latitude > 0 ? 1 : -1; Vector3 up = axis + Vector3.UnitY; up.Normalize(); Vector3 rotAxis = axis; Vector3 yawAxis = Vector3.Cross(axis, up); yawAxis.Normalize(); axis = Vector3.TransformSimple(axis, Quaternion.RotationAxis(yawAxis, yaw)); position = target + axis * height * 35 * 1.15f; Matrix viewTrans = Matrix.LookAtRH(position, target, up); Frustum.View = viewTrans; Frustum.Update(); front = viewTrans.Forward; top = viewTrans.Up; right = viewTrans.Right; Quaternion.RotationMatrix(ref viewTrans, out orientation); }
//static void Vec2Ang() //{ // for (int i = 0; i < 36; i++) // { // Console.Write(i * 10); // Console.Write(' '); // if ((i + 1) % 12 == 0) // Console.WriteLine(); // } // Console.WriteLine(); // for (int i = 0; i < 36; i++) // { // float rad = MathEx.Degree2Radian(i * 10); // Vector2 a = new Vector2((float)Math.Cos(rad), (float)Math.Sin(rad)); // float ang = MathEx.Vector2DirAngle(a); // ang = MathEx.Radian2Degree(ang); // //ang = -ang; // Console.Write(ang); // Console.Write(' '); // if ((i + 1) % 12 == 0) // Console.WriteLine(); // } //} static void PlanetPosition() { for (int i = 0; i < 90; i++) { float deg = MathEx.Degree2Radian(i); Console.WriteLine("degree {0}: {1}", i, PlanetEarth.GetPosition(1, deg)); } }
public TreeBatchModel(RenderSystem rs, ForestInfo info) : base(TreeBatchModelManager.Instance, GetHashString(info)) { this.info = info; this.renderSys = rs; float radlng = MathEx.Degree2Radian(info.Longitude); float radlat = MathEx.Degree2Radian(info.Latitude); Transformation = Matrix.Identity;// PlanetEarth.GetOrientation(radlng, radlat); //Transformation.TranslationValue = PlanetEarth.GetPosition(radlng, radlat); BoundingVolume.Center = PlanetEarth.GetPosition(radlng, radlat); BoundingVolume.Radius = PlanetEarth.GetTileArcLength(MathEx.Degree2Radian(info.Radius)); }
public TerrainMesh(RenderSystem rs, int x, int y, int size) : base(TerrainMeshManager.Instance, GetHashString(x, y, size)) { this.opBuffer = new FastList <RenderOperation>(); this.terrEdgeSize = size; this.tileX = x; this.tileY = y; renderSystem = rs; factory = rs.ObjectFactory; material = new Material(rs); material.CullMode = CullMode.None; material.Ambient = new Color4F(1, 0.5f, 0.5f, 0.5f); material.Diffuse = new Color4F(1f, 1f, 1f, 1f); material.Specular = new Color4F(0, 0, 0, 0); material.Power = 1; material.PriorityHint = RenderPriority.Second; PlanetEarth.TileCoord2CoordNew(x, y, out tileCol, out tileLat); // 估算包围球 { float radtc = MathEx.Degree2Radian(tileCol); float radtl = MathEx.Degree2Radian(tileLat); float rad5 = PlanetEarth.DefaultTileSpan * 0.5f; BoundingSphere.Center = PlanetEarth.GetPosition(radtc + rad5, radtl - rad5); BoundingSphere.Radius = MathEx.Root2 * PlanetEarth.GetTileHeight(rad5 * 2); if (ObjectSpaceChanged != null) { ObjectSpaceChanged(Transformation, BoundingSphere); } } }
public void Parse(ConfigurationSection sect) { float lng = sect.GetSingle("Longitude"); float lat = sect.GetSingle("Latitude"); lng = MathEx.Degree2Radian(lng); lat = MathEx.Degree2Radian(lat); float alt = TerrainData.Instance.QueryHeight(lng, lat); position = PlanetEarth.GetPosition(lng, lat); radius = sect.GetSingle("Radius"); radius = PlanetEarth.GetTileHeight(MathEx.Degree2Radian(radius)); string sfxName = sect["SFX"]; sound = SoundManager.Instance.MakeSoundObjcet(sfxName, null, radius); sound.Position = position; //probability = sect.GetSingle("Probability", 1); }
protected unsafe override void load() { resourceSize = 0; float radlng = MathEx.Degree2Radian(info.Longitude); float radlat = MathEx.Degree2Radian(info.Latitude); float radr = MathEx.Degree2Radian(info.Radius) * 2; TreeOrientation = PlanetEarth.GetOrientation(radlng, radlat); TreeOrientation.TranslationValue = PlanetEarth.GetPosition(radlng, radlat, PlanetEarth.PlanetRadius); int vtxCount = 0; int vtxOffset = 0; int vtxCount2 = 0; int vtxOffset2 = 0; int plantCount = (int)(info.Amount * 0.05f); FastList <byte> vertices2 = new FastList <byte>(plantCount * 2500); FastList <int> indices2 = new FastList <int>(); int partVtxCount2 = 0; FastList <byte> vertices = new FastList <byte>(plantCount * 2500); Dictionary <Material, FastList <int> > indices = new Dictionary <Material, FastList <int> >(); Dictionary <Material, int> partVtxCount = new Dictionary <Material, int>(); plantCount = 0; byte[] vtxBldBuffer = new byte[TreeVertex.Size]; const float AreaWidth = 0.036f; for (float blkLng = radlng - radr; blkLng < radlng + radr; blkLng += AreaWidth) { for (float blkLat = radlat - radr; blkLat < radlat + radr; blkLat += AreaWidth) { float altblk = TerrainData.Instance.QueryHeight(blkLng, blkLat) - 100; if (altblk < 0) { continue; } float density = PlantDensity.Instance.GetPlantDensity(blkLng, blkLat); int count = (int)(density * 2.25f); for (int i = 0; i < count; i++) { float treeLng = blkLng + AreaWidth * Randomizer.GetRandomSingle(); float treeLat = blkLat + AreaWidth * Randomizer.GetRandomSingle(); float alt = TerrainData.Instance.QueryHeight(treeLng, treeLat); PlantDensityData d = PlantDensity.Instance.GetDensity(treeLng, treeLat); int idx = Randomizer.Random(d.Density, PlantDensity.TypeCount); TreeModelData[] mdls = TreeModelLibrary.Instance.Get(idx); TreeModelData meshData = mdls[Randomizer.GetRandomInt(mdls.Length)]; Matrix treeOrientation = PlanetEarth.GetOrientation(treeLng, treeLat); treeOrientation.TranslationValue = PlanetEarth.GetPosition(treeLng, treeLat, PlanetEarth.PlanetRadius + alt * TerrainMeshManager.PostHeightScale); float instanceData = Randomizer.GetRandomSingle(); float theta = instanceData * MathEx.PIf * 2; float rotCos = (float)Math.Cos(theta); float rotSin = (float)Math.Sin(theta); #region 数据 resourceSize += meshData.VertexCount * TreeVertex.Size; vtxCount += meshData.VertexCount; fixed(byte *src = &meshData.VertexData[0]) { VertexPNT1 *ptr = (VertexPNT1 *)src; for (int j = 0; j < meshData.VertexCount; j++) { TreeVertex p; p.pos.X = rotCos * ptr[j].pos.X - rotSin * ptr[j].pos.Z; p.pos.Z = rotSin * ptr[j].pos.X + rotCos * ptr[j].pos.Z; p.pos.Y = ptr[j].pos.Y; p.pos = p.pos * (Game.TreeScale * (instanceData * 0.4f + 0.8f)); Vector3 pp; Vector3.TransformSimple(ref p.pos, ref treeOrientation, out pp); p.pos = pp; p.n.X = rotCos * ptr[j].n.X - rotSin * ptr[j].n.Z; p.n.Z = rotSin * ptr[j].n.Z + rotCos * ptr[j].n.Z; p.n.Y = ptr[j].n.Y; p.tex1 = new Vector3(ptr[j].u, ptr[j].v, instanceData); fixed(byte *dst = &vtxBldBuffer[0]) { Memory.Copy(&p, dst, TreeVertex.Size); } p.tc = new Vector2(treeLng, treeLat); p.tc.X += MathEx.PIf; //p.tc.Y -= MathEx.Degree2Radian(10); p.tc.X = 0.5f * p.tc.X / MathEx.PIf; p.tc.Y = (-p.tc.Y + MathEx.PiOver2) / MathEx.PIf; vertices.Add(vtxBldBuffer); } } Material[] mtrls = meshData.Materials; for (int k = 0; k < mtrls.Length; k++) { Material mtrl = mtrls[k]; FastList <int> idxData; if (!indices.TryGetValue(mtrl, out idxData)) { idxData = new FastList <int>(plantCount * 120); indices.Add(mtrl, idxData); partVtxCount.Add(mtrl, 0); } partVtxCount[mtrl] += meshData.PartVtxCount[k]; int[] meshIdx = meshData.Indices[k]; for (int j = 0; j < meshIdx.Length; j++) { idxData.Add(meshIdx[j] + vtxOffset); } } vtxOffset += meshData.VertexCount; #endregion TreeModelData meshData2 = TreeModelLibrary.Instance.GetTrunk(); #region 树桩 resourceSize += meshData2.VertexCount * TreeVertex.Size; vtxCount2 += meshData2.VertexCount; fixed(byte *src = &meshData2.VertexData[0]) { VertexPNT1 *ptr = (VertexPNT1 *)src; for (int j = 0; j < meshData2.VertexCount; j++) { TreeVertex p; p.pos.X = rotCos * ptr[j].pos.X - rotSin * ptr[j].pos.Z; p.pos.Z = rotSin * ptr[j].pos.X + rotCos * ptr[j].pos.Z; p.pos.Y = ptr[j].pos.Y; p.pos = p.pos * (Game.TreeScale * (instanceData * 0.4f + 0.8f)); Vector3 pp; Vector3.TransformSimple(ref p.pos, ref treeOrientation, out pp); p.pos = pp; p.n.X = rotCos * ptr[j].n.X - rotSin * ptr[j].n.Z; p.n.Z = rotSin * ptr[j].n.Z + rotCos * ptr[j].n.Z; p.n.Y = ptr[j].n.Y; p.tex1 = new Vector3(ptr[j].u, ptr[j].v, instanceData); fixed(byte *dst = &vtxBldBuffer[0]) { Memory.Copy(&p, dst, TreeVertex.Size); } vertices2.Add(vtxBldBuffer); } } material2 = meshData2.Materials[0]; partVtxCount2 += meshData2.PartVtxCount[0]; int[] meshIdx2 = meshData2.Indices[0]; for (int j = 0; j < meshIdx2.Length; j++) { indices2.Add(meshIdx2[j] + vtxOffset2); } vtxOffset2 += meshData2.VertexCount; #endregion plantCount++; } } } // ============================================================================ ObjectFactory fac = renderSys.ObjectFactory; vtxDecl = fac.CreateVertexDeclaration(TreeVertex.Elements); int vtxSize = vtxDecl.GetVertexSize(); vtxBuffer = fac.CreateVertexBuffer(vtxCount, vtxDecl, BufferUsage.Static); vertices.Trim(); vtxBuffer.SetData <byte>(vertices.Elements); vtxBuffer2 = fac.CreateVertexBuffer(vtxCount2, vtxDecl, BufferUsage.Static); vertices2.Trim(); vtxBuffer2.SetData <byte>(vertices2.Elements); int partCount = indices.Count; idxBuffer = new IndexBuffer[partCount]; materials = new Material[partCount]; opBuf = new RenderOperation[partCount]; int index = 0; foreach (KeyValuePair <Material, FastList <int> > e in indices) { FastList <int> list = e.Value; list.Trim(); materials[index] = e.Key; idxBuffer[index] = fac.CreateIndexBuffer(IndexBufferType.Bit32, list.Count, BufferUsage.Static); idxBuffer[index].SetData <int>(list.Elements); resourceSize += sizeof(int) * list.Count; // ============================================================================================== opBuf[index].Material = e.Key; opBuf[index].Geomentry = new GeomentryData(); opBuf[index].Geomentry.BaseIndexStart = 0; opBuf[index].Geomentry.BaseVertex = 0; opBuf[index].Geomentry.IndexBuffer = idxBuffer[index]; opBuf[index].Geomentry.PrimCount = idxBuffer[index].IndexCount / 3; opBuf[index].Geomentry.PrimitiveType = RenderPrimitiveType.TriangleList; opBuf[index].Geomentry.VertexBuffer = vtxBuffer; opBuf[index].Geomentry.VertexCount = partVtxCount[e.Key]; opBuf[index].Geomentry.VertexDeclaration = vtxDecl; opBuf[index].Geomentry.VertexSize = vtxSize; opBuf[index].Sender = this; index++; } indices2.Trim(); idxBuffer2 = fac.CreateIndexBuffer(IndexBufferType.Bit32, indices2.Count, BufferUsage.Static); idxBuffer2.SetData <int>(indices2.Elements); opbuf2 = new RenderOperation[1]; opbuf2[0].Material = material2; opbuf2[0].Geomentry = new GeomentryData(); opbuf2[0].Geomentry.BaseIndexStart = 0; opbuf2[0].Geomentry.BaseVertex = 0; opbuf2[0].Geomentry.IndexBuffer = idxBuffer2; opbuf2[0].Geomentry.PrimCount = idxBuffer2.IndexCount / 3; opbuf2[0].Geomentry.PrimitiveType = RenderPrimitiveType.TriangleList; opbuf2[0].Geomentry.VertexBuffer = vtxBuffer2; opbuf2[0].Geomentry.VertexCount = partVtxCount2; opbuf2[0].Geomentry.VertexDeclaration = vtxDecl; opbuf2[0].Geomentry.VertexSize = vtxSize; opbuf2[0].Sender = this; }
//public float GetHeight(Point pt) //{ // return TerrainMeshManager.PostHeightScale * (heightData[pt.Y][pt.X] / 7f - TerrainMeshManager.PostZeroLevel); //} public Matrix GetTangentSpaceMatrix(Vector2 pa, Vector2 pb) { float yspan = (14.0f / 18.0f) * MathEx.PIf; float y1 = ((yspan * 0.5f - pa.Y) / yspan) * HeightMapHeight; float x1 = ((pa.X + MathEx.PIf) / (2 * MathEx.PIf)) * HeightMapWidth; if (y1 < 0) { y1 += HeightMapHeight; } if (y1 >= HeightMapHeight) { y1 -= HeightMapHeight; } if (x1 < 0) { x1 += HeightMapWidth; } if (x1 >= HeightMapWidth) { x1 -= HeightMapWidth; } float y2 = ((yspan * 0.5f - pb.Y) / yspan) * HeightMapHeight; float x2 = ((pb.X + MathEx.PIf) / (2 * MathEx.PIf)) * HeightMapWidth; if (y2 < 0) { y2 += HeightMapHeight; } if (y2 >= HeightMapHeight) { y2 -= HeightMapHeight; } if (x2 < 0) { x2 += HeightMapWidth; } if (x2 >= HeightMapWidth) { x2 -= HeightMapWidth; } float h1 = TerrainMeshManager.PostHeightScale * (heightData[(int)y1][(int)x1] / 7f - TerrainMeshManager.PostZeroLevel); float h2 = TerrainMeshManager.PostHeightScale * (heightData[(int)y2][(int)x2] / 7f - TerrainMeshManager.PostZeroLevel); Vector3 p1 = PlanetEarth.GetPosition(pa.X, pa.Y, PlanetEarth.PlanetRadius + h1); Vector3 p2 = PlanetEarth.GetPosition(pb.X, pb.Y, PlanetEarth.PlanetRadius + h2); Vector3 dir = p2 - p1; dir.Normalize(); Vector3 n = p1; n.Normalize(); Vector3 bi = Vector3.Cross(dir, n); bi.Normalize(); n = Vector3.Cross(dir, bi); n.Normalize(); Matrix result = Matrix.Identity; result.Right = bi; result.Up = n; result.Forward = -dir; return(result); }
/// <summary> /// This implements the method in resource, to load the mesh data(vertex buffer, index buffer) /// of this terrain tile. /// </summary> protected override void load() { // 读取地形数据 // This line will load the terrain data in this tile. float[] data = TerrainData.Instance.GetData(tileX, tileY, terrEdgeSize); float radtc = MathEx.Degree2Radian(tileCol); float radtl = MathEx.Degree2Radian(tileLat); float radSpan = MathEx.Degree2Radian(10); int vertexCount = terrEdgeSize * terrEdgeSize; int terrEdgeLen = terrEdgeSize - 1; if (terrEdgeSize == 33) { material.SetEffect(EffectManager.Instance.GetModelEffect(TerrainEffect33Factory.Name)); } else { material.SetEffect(EffectManager.Instance.GetModelEffect(TerrainEffect17Factory.Name)); } #region 顶点数据 vtxDecl = factory.CreateVertexDeclaration(TerrainVertex.Elements); vtxBuffer = factory.CreateVertexBuffer(vertexCount, vtxDecl, BufferUsage.WriteOnly); TerrainVertex[] vtxArray = new TerrainVertex[vertexCount]; float cellAngle = radSpan / (float)terrEdgeLen; #region 计算顶点坐标 // Caluclate the position of each vertex // i为纬度方向 // i is in the latitude direction for (int i = 0; i < terrEdgeSize; i++) { // j为经度方向 // j is in the longitude direction for (int j = 0; j < terrEdgeSize; j++) { Vector3 pos = PlanetEarth.GetPosition(radtc + j * cellAngle, radtl - i * cellAngle); int index = i * terrEdgeSize + j; // 计算海拔高度 // calculate the elevation float height = (data[index] - TerrainMeshManager.PostZeroLevel) * TerrainMeshManager.PostHeightScale; //if (height > 0) //{ // height = (height - 0) * TerrainMeshManager.PostHeightScale; //} //else //{ // height *= TerrainMeshManager.PostHeightScale; // height -= 10; // //if (height < -30) // // height = -30; //} Vector3 normal = pos; normal.Normalize(); vtxArray[index].Position = pos + normal * height; // this index is used to generate detailed texture coordinate in vertex shader vtxArray[index].Index = index; // map the texture coordinate for global texturing float curCol = radtc + j * cellAngle; float curLat = radSpan + radtl - i * cellAngle; curCol += MathEx.PIf; curLat -= MathEx.Degree2Radian(10); vtxArray[index].u = 0.5f * curCol / MathEx.PIf; vtxArray[index].v = (-curLat + MathEx.PiOver2) / MathEx.PIf; } } #endregion #endregion #region 索引数据 SharedIndexData sindexData = TerrainMeshManager.Instance.GetIndexData(terrEdgeSize); indexBuffer = sindexData.Index; #endregion #region 构造GeomentryData defGeometryData = new GeomentryData(); defGeometryData.VertexDeclaration = vtxDecl; defGeometryData.VertexSize = TerrainVertex.Size; defGeometryData.VertexBuffer = vtxBuffer; defGeometryData.IndexBuffer = indexBuffer; defGeometryData.PrimCount = indexBuffer.IndexCount / 3; defGeometryData.VertexCount = terrEdgeSize * terrEdgeSize; defGeometryData.PrimitiveType = RenderPrimitiveType.TriangleList; defGeometryData.BaseVertex = 0; #endregion vtxBuffer.SetData <TerrainVertex>(vtxArray); }