private void GetPlayerInputs() { horizontal = Input.GetAxis("Horizontal"); vertical = Input.GetAxis("Vertical"); mouseHorizontal = Input.GetAxis("Mouse X"); mouseVertical = Input.GetAxis("Mouse Y"); if (Input.GetButtonDown("Sprint")) { isSprinting = true; } if (Input.GetButtonUp("Sprint")) { isSprinting = false; } if (isGrounded && Input.GetButtonDown("Jump")) { jumpRequest = true; } if (highlightBlock.gameObject.activeSelf) { Vector3s pos = World.vs(highlightBlock.position); Chunk chunk = world.GetChunkFromVector3s(pos); BlockType id = BlockType.Air; if (chunk != null) { id = chunk.model.voxelMap[(int)pos.x % VoxelData.ChunkWidth, (int)pos.y % VoxelData.ChunkHeight, (int)pos.z % VoxelData.ChunkWidth].id; } ProcessMouseActivity(id); } }
/// <summary> /// Writes a 6-byte <see cref="Vector3s"/> value to the data stream in XYZ order. This function /// expects a Y-up vector. /// </summary> /// <param name="binaryWriter">The current <see cref="BinaryWriter"/> object.</param> /// <param name="vector">The Vector to write.</param> /// <param name="storeAs">Which axis configuration the read vector should be stored as.</param> public static void WriteVector3s(this BinaryWriter binaryWriter, Vector3s vector, AxisConfiguration storeAs = AxisConfiguration.ZUp) { switch (storeAs) { case AxisConfiguration.Native: case AxisConfiguration.YUp: { binaryWriter.Write(vector.X); binaryWriter.Write(vector.Y); binaryWriter.Write(vector.Z); break; } case AxisConfiguration.ZUp: { binaryWriter.Write(vector.X); binaryWriter.Write((short)(vector.Z * -1)); binaryWriter.Write(vector.Y); break; } default: { throw new ArgumentOutOfRangeException(nameof(storeAs), storeAs, null); } } }
// 從實際座標得到區塊座標 ChunkCoord GetChunkCoordFromVector3s(Vector3s pos) { int x = Mathf.FloorToInt(pos.x / VoxelData.ChunkWidth); int z = Mathf.FloorToInt(pos.z / VoxelData.ChunkWidth); return(new ChunkCoord(x, z)); }
// 從實際座標得到區塊 public Chunk GetChunkFromVector3s(Vector3s pos) { int x = Mathf.FloorToInt(pos.x / VoxelData.ChunkWidth); int z = Mathf.FloorToInt(pos.z / VoxelData.ChunkWidth); return(chunks[x, z]); }
// 修改方塊矩陣 public void UpdateChunk() { while (modifications.Count > 0) { VoxelMod v = modifications.Dequeue(); Vector3s pos = v.position -= position; voxelMap[(int)pos.x, (int)pos.y, (int)pos.z].id = v.id; } ClearMeshData(); //CalculateLight(); for (int y = 0; y < VoxelData.ChunkHeight; y++) { for (int x = 0; x < VoxelData.ChunkWidth; x++) { for (int z = 0; z < VoxelData.ChunkWidth; z++) { if (world.blocks[(int)voxelMap[x, y, z].id].isSolid) { UpdateMeshData(new Vector3s(x, y, z)); } } } } }
public Vector3s Read(int position, Vector3s fallback) { Vector3s o; o.X = Read(position, fallback.X); o.Y = Read(position + 2, fallback.Y); o.Z = Read(position + 4, fallback.Z); return(o); }
[Show, Category(Single)] void ClearSingles() { Ints.Clear(); Strings.Clear(); Floats.Clear(); Bools.Clear(); Vector3s.Clear(); Colors.Clear(); }
// 計算亮度 public void CalculateLight() { Queue <Vector3s> litVoxels = new Queue <Vector3s>(); for (int x = 0; x < VoxelData.ChunkWidth; x++) { for (int z = 0; z < VoxelData.ChunkWidth; z++) { float lightRay = 1f; for (int y = VoxelData.ChunkHeight - 1; y > -1; y--) { VoxelState thisVoxel = voxelMap[x, y, z]; if (thisVoxel.id > 0 && world.blocks[(int)thisVoxel.id].transparency < lightRay) { lightRay = world.blocks[(int)thisVoxel.id].transparency; } thisVoxel.globalLightPercent = lightRay; voxelMap[x, y, z] = thisVoxel; if (lightRay > VoxelData.lightFalloff) { litVoxels.Enqueue(new Vector3s(x, y, z)); } } } } while (litVoxels.Count > 0) { Vector3s v = litVoxels.Dequeue(); for (int p = 0; p < 6; p++) { Vector3s currentVoxel = v + VoxelData.faceChecks[p]; int xCheck = (int)currentVoxel.x; int yCheck = (int)currentVoxel.y; int zCheck = (int)currentVoxel.z; Vector3s neighbor = new Vector3s(currentVoxel.x, currentVoxel.y, currentVoxel.z); if (IsVoxelInChunk(xCheck, yCheck, zCheck)) { if (voxelMap[xCheck, yCheck, zCheck].globalLightPercent < voxelMap[(int)v.x, (int)v.y, (int)v.z].globalLightPercent - VoxelData.lightFalloff) { voxelMap[xCheck, yCheck, zCheck].globalLightPercent = voxelMap[(int)v.x, (int)v.y, (int)v.z].globalLightPercent - VoxelData.lightFalloff; if (voxelMap[xCheck, yCheck, zCheck].globalLightPercent > VoxelData.lightFalloff) { litVoxels.Enqueue(neighbor); } } } } } }
/// <summary> /// Initializes a new instance of the <see cref="Vector8s"/> using the specified vector and values. /// </summary> /// <param name="value">A vector containing the values with which to initialize the first 3 components</param> /// <param name="v3">Value for the V3 component of the vector.</param> /// <param name="v4">Value for the V4 component of the vector.</param> /// <param name="v5">Value for the V5 component of the vector.</param> /// <param name="v6">Value for the V6 component of the vector.</param> /// <param name="v7">Value for the V7 component of the vector.</param> public Vector8s(Vector3s value, short v3, short v4, short v5, short v6, short v7, short v8, short v9, short v10) { V0 = value.X; V1 = value.Y; V2 = value.Z; V3 = v3; V4 = v4; V5 = v5; V6 = v6; V7 = v7; }
public void Read(BinaryReaderEx br) { position = new Vector3s(br); angle = new Vector3s(br); unk11 = br.ReadByte(); unk12 = br.ReadByte(); unk2 = br.ReadUInt16(); unk3 = br.ReadUInt16(); pos = br.ReadByte(); unk5 = br.ReadByte(); }
// 用實際座標確認方塊是否在世界中 bool IsVoxelInWorld(Vector3s pos) { if (pos.x >= 0 && pos.x < VoxelData.WorldSizeInVoxels && pos.y >= 0 && pos.y < VoxelData.ChunkHeight && pos.z >= 0 && pos.z < VoxelData.WorldSizeInVoxels) { return(true); } else { return(false); } }
// 用絕對座標取得方塊 public VoxelState GetVoxelFromGlobalVector3s(Vector3s pos) { int xCheck = (int)pos.x; int yCheck = (int)pos.y; int zCheck = (int)pos.z; xCheck -= (int)position.x; zCheck -= (int)position.z; return(voxelMap[xCheck, yCheck, zCheck]); }
/// <summary> /// Writes a 8-byte <see cref="Quaternion"/> to the data stream. This is a packed format of a normal 32-bit quaternion with /// some data loss. /// </summary> /// <param name="binaryWriter">The current <see cref="BinaryWriter"/> object.</param> /// <param name="quaternion">The quaternion to write.</param> public static void WriteQuaternion16(this BinaryWriter binaryWriter, Quaternion quaternion) { var vector = new Vector3s ( ExtendedData.FloatQuatValueToShort(quaternion.X), ExtendedData.FloatQuatValueToShort(quaternion.Y), ExtendedData.FloatQuatValueToShort(quaternion.Z) ); binaryWriter.WriteVector3s(vector); binaryWriter.Write(ExtendedData.FloatQuatValueToShort(quaternion.W)); }
public void Read(BinaryReaderEx br) { flag = br.ReadUInt16(); id = br.ReadUInt16(); v1 = new Vector3s(br); v2 = new Vector3s(br); v3 = new Vector3s(br); v4 = new Vector3s(br); ptrQuadBlock = br.ReadUInt32(); //Console.WriteLine(ToString()); }
// 用方格座標取得方塊 public VoxelState CheckVoxel(Vector3s pos) { int x = (int)pos.x; int y = (int)pos.y; int z = (int)pos.z; if (!IsVoxelInChunk(x, y, z)) { return(world.GetVoxelState(pos + position)); } return(voxelMap[x, y, z]); }
// 修改周圍方塊 public void UpdateSurroundingVoxels(int x, int y, int z) { Vector3s thisVoxel = new Vector3s(x, y, z); for (int p = 0; p < 6; p++) { Vector3s currentVoxel = thisVoxel + VoxelData.faceChecks[p]; if (!IsVoxelInChunk((int)currentVoxel.x, (int)currentVoxel.y, (int)currentVoxel.z)) { world.chunksToUpdate.Insert(0, world.GetChunkFromVector3s(currentVoxel + position)); } } }
// 刷新網格與材質變數 public void UpdateMeshData(Vector3s pos) { int x = (int)pos.x; int y = (int)pos.y; int z = (int)pos.z; BlockType blockID = voxelMap[x, y, z].id; // 刷新六面資料 for (int p = 0; p < 6; p++) { VoxelState neighbor = CheckVoxel(pos + VoxelData.faceChecks[p]); // 周邊方塊不會擋住此方塊才顯示 if (neighbor != null && world.blocks[(int)neighbor.id].renderNeighborFaces) { float lightLevel = neighbor.globalLightPercent; for (int i = 0; i < 4; i++) { vertices.Add(pos + VoxelData.voxelVerts[VoxelData.voxelTris[p, i]]); // 網格座標 normals.Add(VoxelData.faceChecks[p]); // 網格方向 //colors.Add(new Colors(0, 0, 0, lightLevel)); // 材質亮度 } AddTexture(world.blocks[(int)blockID].GetTextureID(p)); if (!world.blocks[(int)neighbor.id].renderNeighborFaces) // 不透明材質 的兩個三角形座標 { triangles.Add(vertexIndex); triangles.Add(vertexIndex + 1); triangles.Add(vertexIndex + 2); triangles.Add(vertexIndex + 2); triangles.Add(vertexIndex + 1); triangles.Add(vertexIndex + 3); } else // 透明材質 的兩個三角形座標 { transparentTriangles.Add(vertexIndex); transparentTriangles.Add(vertexIndex + 1); transparentTriangles.Add(vertexIndex + 2); transparentTriangles.Add(vertexIndex + 2); transparentTriangles.Add(vertexIndex + 1); transparentTriangles.Add(vertexIndex + 3); } vertexIndex += 4; } } }
// 用實際座標得到方塊 public VoxelState GetVoxelState(Vector3s pos) { ChunkCoord thisChunk = new ChunkCoord(pos); if (!IsChunkInWorld(thisChunk) || pos.y < 0 || pos.y > VoxelData.ChunkHeight) { return(null); } if (chunks[thisChunk.x, thisChunk.z] != null && chunks[thisChunk.x, thisChunk.z].isEditable) { return(chunks[thisChunk.x, thisChunk.z].model.GetVoxelFromGlobalVector3s(pos)); } return(new VoxelState(GetInitialVoxel(pos))); }
// 用實際座標確認方塊是否為實體 public bool CheckForVoxel(Vector3s pos) { ChunkCoord thisChunk = new ChunkCoord(pos); if (!IsChunkInWorld(thisChunk) || pos.y < 0 || pos.y > VoxelData.ChunkHeight) { return(false); } if (chunks[thisChunk.x, thisChunk.z] != null && chunks[thisChunk.x, thisChunk.z].isEditable) { return(blocks[(int)chunks[thisChunk.x, thisChunk.z].model.GetVoxelFromGlobalVector3s(pos).id].isSolid); } return(blocks[(int)GetInitialVoxel(pos)].isSolid); }
private Vector3 InterpolatedPosition(float t) { if (Application.isPlaying && nav.paths != null && nav.paths.Count > 0) { int pathLen = nav.paths[0].frames.Count; var frames = nav.paths[0].frames.ToArray(); Vector3s s0 = frames[(int)t % pathLen].position; Vector3 a0 = s0.GetVector3(); a0.y += 2f; Vector3s s1 = frames[(int)(t + 1) % pathLen].position; Vector3 a1 = s1.GetVector3(); a1.y += 2f; return(Vector3.Lerp(a0, a1, Time.time % 1.0f)); } return(camera.transform.position); }
public void Read(BinaryReaderEx br) { br.Jump(256 + 2); int datasize = br.ReadInt16(); br.Seek(2 + 2 + 4 + 4 + 4 + 5 * 4); StringBuilder sb = new StringBuilder(); for (int i = 0; i < datasize / 6; i++) { Vector3s v = new Vector3s(br); sb.AppendFormat("v {0}\r\n", v.ToString(CTRFramework.VecFormat.Numbers)); } File.WriteAllText("testghost.obj", sb.ToString()); }
public PickupHeader(BinaryReaderEx br) { name = System.Text.Encoding.ASCII.GetString(br.ReadBytes(16)).Replace("\0", ""); modelOffset = br.ReadUInt32(); scale = new Vector4s(br); if (scale.W != 0) { Console.WriteLine("!! scale.W != 0 !! W = " + scale.W); } null1 = br.ReadUInt32(); if (null1 != 0) { Console.WriteLine("!! null != 0 !! null1 = " + null1); } unk1 = br.ReadUInt32(); br.BaseStream.Position += 4 * 3; position = new Vector3s(br); angle = new Vector3s(br); evt = br.ReadInt32(); int x = (int)br.BaseStream.Position; br.Jump(modelOffset); ModelName = br.ReadStringFixed(16); br.BaseStream.Position = x; }
public PosAng(Vector3s pos, Vector3s ang) { Position = pos; Angle = ang; }
/// <summary>Read a <see cref="Vector3s"/>.</summary> public static void ReadVector3s(this BinaryReader reader , out Vector3s result) { result.X = reader.ReadInt16(); result.Y = reader.ReadInt16(); result.Z = reader.ReadInt16(); return; }
/// <summary>Read an array of <c>Vector3s</c> values.</summary> public static Vector3s[] ReadArrayVector3s(this BinaryReader reader, int count) { Vector3s[] array = new Vector3s[count]; reader.ReadArray(array, 0, count); return array; }
public ChunkCoord(Vector3s pos) { x = (int)(pos.x / VoxelData.ChunkWidth); z = (int)(pos.z / VoxelData.ChunkWidth); }
public BlockType id; // 修改方塊ID public VoxelMod() { position = new Vector3s(); id = 0; }
public VoxelMod(Vector3s _position, BlockType _id) { position = _position; id = _id; }
// 用實際座標取得生態圈的方塊 public BlockType GetInitialVoxel(Vector3s pos) { int yPos = Mathf.FloorToInt(pos.y); /* 不變規則 */ // 超出世界回傳空氣 if (!IsVoxelInWorld(pos)) { return(BlockType.Air); } // 達到世界底部回傳基岩 if (yPos == 0) { return(BlockType.Bedrock); } /* 生態圈選擇規則 */ int solidGroundHeight = 42; float sumOfHeights = 0f; int count = 0; float strongestWeight = 0f; int strongestBiomeIndex = 0; for (int i = 0; i < biomes.Length; i++) { float weight = Noise.Get2DPerlin(new Vector2(pos.x, pos.z), biomes[i].offset, biomes[i].scale); // 檢查哪個生態圈的加權值 (Perlin雜訊值) 較高 if (weight > strongestWeight) { strongestWeight = weight; strongestBiomeIndex = i; } // 計算生態圈的高度 (雜訊值 * 設定高度) float height = biomes[i].terrainHeight * Noise.Get2DPerlin(new Vector2(pos.x, pos.z), 0, biomes[i].terrainScale) * weight; // 如果高度有效那麼加進平均 if (height > 0) { sumOfHeights += height; count++; } } // 設定最高加權值的生態圈 BiomeAttributes biome = biomes[strongestBiomeIndex]; // 生態圈平均高度 sumOfHeights /= count; int terrainHeight = Mathf.FloorToInt(sumOfHeights + solidGroundHeight); /* 生態圈地表規則 */ BlockType voxelValue = 0; if (yPos == terrainHeight) { voxelValue = biome.surfaceBlock; } else if (yPos < terrainHeight && yPos > terrainHeight - 4) { voxelValue = biome.subSurfaceBlock; } else if (yPos > terrainHeight) { return(BlockType.Air); } else { voxelValue = BlockType.Stone; } /* 生態圈內部礦物規則 */ if (voxelValue == BlockType.Stone) { foreach (Lode lode in biome.lodes) { if (yPos > lode.minHeight && yPos < lode.maxHeight) { if (Noise.Get3DPerlin(sv(pos), lode.noiseOffset, lode.scale, lode.threshold)) { voxelValue = lode.blockID; } } } } /* 生態圈表面植被規則 */ if (yPos == terrainHeight && biome.placeMajorFlora) { if (Noise.Get2DPerlin(new Vector2(pos.x, pos.z), 0, biome.majorFloraZoneScale) > biome.majorFloraZoneThreshold) { if (Noise.Get2DPerlin(new Vector2(pos.x, pos.z), 0, biome.majorFloraPlacementScale) > biome.majorFloraPlacementThreshold) { modifications.Enqueue(Structure.GenerateMajorFlora(biome.majorFloraIndex, sv(pos), biome.minHeight, biome.maxHeight)); } } } return(voxelValue); }
public void Read(BinaryReaderEx br) { Position = new Vector3s(br); Angle = new Vector3s(br); }
public static Vector3 sv(Vector3s a) { return(new Vector3(a.x, a.y, a.z)); }
public void Read(BinaryReaderEx br) { name = br.ReadStringFixed(16); unk0 = br.ReadInt32(); lodDistance = br.ReadInt16(); billboard = br.ReadInt16(); Console.WriteLine($"CtrHeader: {name}"); if (unk0 != 0) { Helpers.Panic(this, $"check unusual unk0 value = {unk0}"); } if (billboard > 1) { Helpers.Panic(this, $"check unusual billboard value = {billboard}"); } scale = new Vector4s(br); ptrCmd = br.ReadInt32(); ptrVerts = br.ReadInt32(); ptrTex = br.ReadInt32(); ptrClut = br.ReadInt32(); unk3 = br.ReadInt32(); numAnims = br.ReadInt32(); ptrAnims = br.ReadInt32(); unk4 = br.ReadInt32(); if (unk3 != 0) { Helpers.Panic(this, $"check unusual unk3 value = {unk3}"); } if (unk4 != 0) { Helpers.Panic(this, $"check unusual unk4 value = {unk4}"); } long pos = br.BaseStream.Position; //read all drawing commands br.Jump(ptrCmd); cmdNum = br.ReadInt32(); uint x; do { x = br.ReadUInt32Big(); if (x != 0xFFFFFFFF) { drawList.Add(new CtrDraw(x)); } }while (x != 0xFFFFFFFF); //should read anims here /* * if (numAnims > 0) * { * for (int f = 0; f < numAnims; f++) * { * br.Jump(ptrAnims + f * 4); * br.Jump(br.ReadInt32()); * anims.Add(new CTRAnim(br)); * } * } */ //define temporary arrays Vector4b[] clr = new Vector4b[3]; //color buffer Vector3s[] crd = new Vector3s[4]; //face buffer Vector3s[] stack = new Vector3s[256]; //vertex buffer int maxv = 0; int maxc = 0; int maxt = 0; //one pass through all draw commands to get the array lengths foreach (var draw in drawList) { //only increase vertex count for commands that don't take vertex from stack if (!draw.flags.HasFlag(CtrDrawFlags.v)) { maxv++; } //simply find max color index if (draw.colorIndex > maxc) { maxc = draw.colorIndex; } //find max index, but 0 means no texture. if (draw.texIndex > 0) { if (draw.texIndex - 1 > maxt) { maxt = draw.texIndex; } } Console.WriteLine(draw.ToString()); } Console.WriteLine("maxv: " + maxv); Console.WriteLine("maxc: " + maxc); Console.WriteLine("maxt: " + maxt); //int ppos = (int)br.BaseStream.Position; br.Jump(ptrClut); for (int k = 0; k <= maxc; k++) { cols.Add(new Vector4b(br)); } //if static model if (!IsAnimated) { br.Jump(ptrVerts); posOffset = new Vector4s(br); Console.WriteLine(posOffset); br.Skip(16); vrenderMode = br.ReadInt32(); if (!(new List <int> { 0x1C, 0x22 }).Contains(vrenderMode)) { Helpers.Panic(this, $"check vrender {vrenderMode.ToString("X8")}"); } } else { //jump to first animation, read header and jump to vertex garbage br.Jump(ptrAnims); int ptr = br.ReadInt32(); br.Jump(ptr); CtrAnim anim = CtrAnim.FromReader(br); Console.WriteLine(anim.name + " " + anim.numFrames); br.Skip(0x1C); Console.WriteLine(br.HexPos()); posOffset = new Vector4s(0, 0, 0, 0); } //read vertices for (int k = 0; k < maxv; k++) { vtx.Add(new Vector3b(br)); } foreach (var v in vtx) { Console.WriteLine(v.ToString(VecFormat.Hex)); } List <Vector3s> vfixed = new List <Vector3s>(); foreach (var v in vtx) { vfixed.Add(new Vector3s(v.X, v.Y, v.Z)); } foreach (Vector3s v in vfixed) { //scale vertices v.X = (short)((((float)v.X / 255.0f - 0.5) * scale.X)); v.Y = (short)((((float)v.Y / 255.0f - 0.5) * scale.Z)); v.Z = (short)((((float)v.Z / 255.0f) * scale.Y)); //flip axis short zz = v.Z; v.Z = (short)-v.Y; v.Y = zz; } int vertexIndex = 0; int stripLength = 0; //process all commands foreach (CtrDraw d in drawList) { //if we got no stack vertex flag if (!d.flags.HasFlag(CtrDrawFlags.v)) { //push vertex from the array to the buffer stack[d.stackIndex] = vfixed[vertexIndex]; vertexIndex++; } //push new vertex from stack crd[0] = crd[1]; crd[1] = crd[2]; crd[2] = crd[3]; crd[3] = stack[d.stackIndex]; if (d.flags.HasFlag(CtrDrawFlags.l)) { crd[1] = crd[0]; } //push new color clr[0] = clr[1]; clr[1] = clr[2]; clr[2] = cols[d.colorIndex]; //if got reset flag, reset tristrip vertex counter if (d.flags.HasFlag(CtrDrawFlags.s)) { stripLength = 0; } //if we got 3 indices in tristrip (0,1,2) if (stripLength >= 2) { //read 3 vertices and push to the array for (int z = 1; z < 4; z++) { Vertex v = new Vertex(); v.coord = new Vector4s(crd[z].X, crd[z].Y, crd[z].Z, 0); v.color = clr[z - 1]; v.color_morph = v.color; verts.Add(v); } //ig got normal flag, change vertex order to flip normals if (!d.flags.HasFlag(CtrDrawFlags.n)) { Vertex v = verts[verts.Count - 1]; verts[verts.Count - 1] = verts[verts.Count - 3]; verts[verts.Count - 3] = v; } } stripLength++; } //read texture layouts br.Jump(ptrTex); uint[] texptrs = br.ReadArrayUInt32(maxt); Console.WriteLine("texptrs: " + texptrs.Length); foreach (uint t in texptrs) { Console.WriteLine(t.ToString("X8")); br.Jump(t); TextureLayout tx = TextureLayout.FromStream(br); tl.Add(tx); Console.WriteLine(tx.ToString()); } Console.WriteLine("tlcnt: " + tl.Count); br.BaseStream.Position = pos; }