From de76d2dec0fc44d59290336678b2535c3d6b9fc4 Mon Sep 17 00:00:00 2001 From: Tungdv Date: Wed, 15 Oct 2025 18:14:53 +0700 Subject: [PATCH] fix: update struct in logic terrain. --- Assets/PerfectWorld/Scene/Boostrap.unity | 109 +++++++ .../Scripts/Managers/A3DTerrain2.cs | 301 ++++++++++++++---- .../Scripts/Managers/A3DTerrain2LOD.cs | 9 + .../Scripts/Managers/A3DTerrain2LOD.cs.meta | 2 + Assets/PerfectWorld/Scripts/Managers/ARect.cs | 280 ++++++++++++++++ .../Scripts/Managers/ARect.cs.meta | 2 + Assets/Scripts/Move/EC_CDR.cs | 85 ++--- 7 files changed, 673 insertions(+), 115 deletions(-) create mode 100644 Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs create mode 100644 Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs.meta create mode 100644 Assets/PerfectWorld/Scripts/Managers/ARect.cs create mode 100644 Assets/PerfectWorld/Scripts/Managers/ARect.cs.meta diff --git a/Assets/PerfectWorld/Scene/Boostrap.unity b/Assets/PerfectWorld/Scene/Boostrap.unity index 8fc81705c0..8af98d5485 100644 --- a/Assets/PerfectWorld/Scene/Boostrap.unity +++ b/Assets/PerfectWorld/Scene/Boostrap.unity @@ -164,6 +164,114 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: _nextSceneName: LoginScene +--- !u!1 &428240946 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 428240950} + - component: {fileID: 428240949} + - component: {fileID: 428240948} + - component: {fileID: 428240947} + m_Layer: 0 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!65 &428240947 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 428240946} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &428240948 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 428240946} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &428240949 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 428240946} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &428240950 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 428240946} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1001 &506356661 PrefabInstance: m_ObjectHideFlags: 0 @@ -586,3 +694,4 @@ SceneRoots: - {fileID: 591506937} - {fileID: 105404091} - {fileID: 506356661} + - {fileID: 428240950} diff --git a/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs index 8ce44da6a3..f2d6deeda0 100644 --- a/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs +++ b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs @@ -1,68 +1,185 @@ using CSNetwork.GPDataType; using UnityEngine; +using ARectI = BrewMonster.Scripts.ARect; +using ARectF = BrewMonster.Scripts.ARect; +using BlockArray = System.Collections.Generic.List; +using BrewMonster.Scripts.Player; +using WORD = System.UInt16; namespace BrewMonster.Scripts.World { - public class A3DTerrain2 + public class A3DTerrain2Block { - protected ACTBLOCKS[] m_pCurActBlocks; // Currently active block array - - // Active blocks - public struct ACTBLOCKS + // Trerrain2 vertex format when use lightmap + public struct A3DTRN2VERTEX1 { - public ARectI rcArea; // Active area represented in blocks - public BlockArray aBlocks; // Active block array - - public ACTBLOCKS() - { - aBlocks = new BlockArray[128]; - } - - ARectI rcArea; // Active area represented in blocks - BlockArray aBlocks; // Active block array - - // Get block object at specified row, column. - A3DTerrain2Block* GetBlock(int r, int c, bool bClear) - { - ASSERT(rcArea.PtInRect(c, r)); - - int iIndex = GetBlockIndex(r, c); - A3DTerrain2Block* pBlock = aBlocks[iIndex]; - - if (bClear) - aBlocks[iIndex] = NULL; - - return pBlock; - } - - // Set block object at specified row, column - void SetBlock(int r, int c, A3DTerrain2Block* pBlock) - { - ASSERT(rcArea.PtInRect(c, r)); - int iIndex = GetBlockIndex(r, c); - aBlocks[iIndex] = pBlock; - } - - // Get block index in aBlocks - int GetBlockIndex(int r, int c) - { - return (r - rcArea.top) * rcArea.Width() + c - rcArea.left; - } + public float vPosX; // PositionX + public float vPosY; // PositionY + public float vPosZ; // PositionZ + public float vNormalX; // NormalX + public float vNormalY; // NormalY + public float vNormalZ; // NormalZ + public float u1, v1; // Texture coordinates project on xz + public float u2, v2; // Texture coordinates project on xy + public float u3, v3; // Texture coordinates project on yz + public float u4, v4; // Texture coordinate of layer mask }; + // Terrain2 vertex format when use vertex-light (not lightmap) + struct A3DTRN2VERTEX2 + { + public float vPosX; // Position X + public float vPosY; // Position Y + public float vPosZ; // Position Z + public uint dwDiffuse; // Diffuse color + public uint dwSpecular; // Specular color + public float u1, v1; // Texture coordinates project on xz + public float u2, v2; // Texture coordinates project on xy + public float u3, v3; // Texture coordinates project on yz + public float u4, v4; // Texture coordinate of layer mask + }; + + public bool m_bDataLoaded = false; // Data loaded flag + public bool IsDataLoaded() { return m_bDataLoaded; } + public uint m_dwBlockFlags; // Block flags + public A3DAABB m_aabbBlock; // Block postion and size in whole world + A3DTRN2VERTEX1[] m_aVertices1; // Vertex buffer, ps version + A3DTRN2VERTEX2[] m_aVertices2; // Vertex buffer, non-ps version + + // Get block's position and size in whole world + public A3DAABB GetBlockAABB() { return m_aabbBlock; } + // Get flag for this whole block unable for GetPosHeight + public bool IsNoPosHeight() + { + return (m_dwBlockFlags & Block_flags_masks.T2BKFLAG_NOPOSHEIGHT) != 0; + } + + // Get vertex + public A3DVECTOR3 GetVertexPos(int n) + { + if (m_aVertices1 != null && m_aVertices1.Length > n) + return new A3DVECTOR3(m_aVertices1[n].vPosX, m_aVertices1[n].vPosY, m_aVertices1[n].vPosZ); + else + { + //ASSERT(m_aVertices2); + return new A3DVECTOR3(m_aVertices2[n].vPosX, m_aVertices2[n].vPosY, m_aVertices2[n].vPosZ); + } + } + } + + public class A3DTerrain2 + { + public ACTBLOCKS m_pCurActBlocks; // Currently active block array + public ARectF m_rcTerrain; // Whole terrain area in logic unit (metres) + public float m_fBlockSize = 0; // Block size (on x and z axis) in logic unit (metres) + public int m_iBlockGrid = 0; // Each block has m_iBlockGrid * m_iBlockGrid terrain grids + public float m_fGridSize; // Terrain grid size (on x and z axis) in logic unit (metres) + public A3DTerrain2LOD m_pLODMan; // LOD manager + + // Get grid faces of specified area + public bool GetFacesOfArea(A3DVECTOR3 vCenter, int iGridWid, int iGridLen, A3DVECTOR3 pVertBuf, WORD pIdxBuf) + { + if (m_pCurActBlocks.rcArea.IsEmpty()) + return false; + + float fInvGridSize = 1.0f / m_fGridSize; + + ARectI rcGrid = new ARectI(); + rcGrid.left = (int)((vCenter.x - m_rcTerrain.left) * fInvGridSize) - (iGridWid >> 1); + rcGrid.top = (int)((m_rcTerrain.top - vCenter.z) * fInvGridSize) - (iGridLen >> 1); + rcGrid.right = rcGrid.left + iGridWid; + rcGrid.bottom = rcGrid.top + iGridLen; + + return GetFacesOfArea(rcGrid, pVertBuf, pIdxBuf); + } + + public bool GetFacesOfArea(ARectI rcGridArea, A3DVECTOR3 pVertBuf, WORD pIdxBuf) + { + if (m_pCurActBlocks.rcArea.IsEmpty()) + return false; + + float fInvGridSize = 1.0f / m_fGridSize; + + ARectI rcGrid = rcGridArea; + + int iMaxGrid = m_iNumAllBlockCol * m_iBlockGrid; + AAssist.a_Clamp(ref rcGrid.left, 0, iMaxGrid); + AAssist.a_Clamp(ref rcGrid.right, 0, iMaxGrid); + iMaxGrid = m_iNumAllBlockRow * m_iBlockGrid; + AAssist.a_Clamp(ref rcGrid.top, 0, iMaxGrid); + AAssist.a_Clamp(ref rcGrid.bottom, 0, iMaxGrid); + + if (rcGrid.IsEmpty()) + return false; + + ARectI rcBlock = new ARectI(); + rcBlock.left = rcGrid.left / m_iBlockGrid; + rcBlock.top = rcGrid.top / m_iBlockGrid; + rcBlock.right = (rcGrid.right - 1) / m_iBlockGrid; + rcBlock.bottom = (rcGrid.bottom - 1) / m_iBlockGrid; + + int r, c; + + // Ensure all blocks in active area and have been loaded + for (r = rcBlock.top; r <= rcBlock.bottom; r++) + { + for (c = rcBlock.left; c <= rcBlock.right; c++) + { + if (!m_pCurActBlocks.rcArea.PtInRect(c, r) || + !m_pCurActBlocks.GetBlock(r, c, false)) + return false; + } + } + + WORD pDestIdx = pIdxBuf; + + for (r = rcBlock.top; r <= rcBlock.bottom; r++) + { + ARectI rect = new ARectI(); + rect.left = rcBlock.left * m_iBlockGrid; + rect.top = r * m_iBlockGrid; + rect.right = rect.left + m_iBlockGrid; + rect.bottom = rect.top + m_iBlockGrid; + + for (c = rcBlock.left; c <= rcBlock.right; c++) + { + A3DTerrain2Block pBlock = m_pCurActBlocks.GetBlock(r, c, false); + //ASSERT(pBlock); + + ARectI rc = rcGrid & rect; + //ASSERT(!rc.IsEmpty()); + + int dx = rc.left - rcGrid.left; + int dy = rc.top - rcGrid.top; + int iBaseVert = dy * (rcGrid.Width() + 1) + dx; + A3DVECTOR3 pVertDest = pVertBuf + iBaseVert; + + int sx = rc.left - rect.left; + int sy = rc.top - rect.top; + + pBlock.CopyFaces(pVertDest, pDestIdx, rc.Width(), rc.Height(), rcGrid.Width() + 1, iBaseVert, sx, sy); + + pDestIdx += rc.Width() * rc.Height() * 6; + rect.left += m_iBlockGrid; + rect.right += m_iBlockGrid; + } + } + + return true; + } // Get height and normal of specified position - public float GetPosHeight(A3DVECTOR3 vPos, A3DVECTOR3? pvNormal = null) + public float GetPosHeight(A3DVECTOR3 vPos, ref A3DVECTOR3 pvNormal) { // Give a default value to normal - if (pvNormal.HasValue) - pvNormal.Value.Clear(); + if (pvNormal != null) + pvNormal.Clear(); if (m_pCurActBlocks.rcArea.IsEmpty()) return 0.0f; // Currenly active area AABB - ARectF rcActive; + ARectF rcActive = new ARectF(); rcActive.left = m_rcTerrain.left + m_pCurActBlocks.rcArea.left * m_fBlockSize; rcActive.top = m_rcTerrain.top - m_pCurActBlocks.rcArea.top * m_fBlockSize; rcActive.right = rcActive.left + m_pCurActBlocks.rcArea.Width() * m_fBlockSize; @@ -76,12 +193,12 @@ namespace BrewMonster.Scripts.World float fInvBlockSize = 1.0f / m_fBlockSize; int iCol = (int)((vPos.x - rcActive.left) * fInvBlockSize); int iRow = (int)(-(vPos.z - rcActive.top) * fInvBlockSize); - a_Clamp(iCol, 0, m_pCurActBlocks.rcArea.Width() - 1); - a_Clamp(iRow, 0, m_pCurActBlocks.rcArea.Height() - 1); + AAssist.a_Clamp(ref iCol, 0, m_pCurActBlocks.rcArea.Width() - 1); + AAssist.a_Clamp(ref iRow, 0, m_pCurActBlocks.rcArea.Height() - 1); int iBlock = iRow * m_pCurActBlocks.rcArea.Width() + iCol; - A3DTerrain2Block* pBlock = m_pCurActBlocks.aBlocks[iBlock]; - if (!pBlock || !pBlock.IsDataLoaded()) + A3DTerrain2Block pBlock = m_pCurActBlocks.aBlocks[iBlock]; + if (pBlock == null || !pBlock.IsDataLoaded()) return 0.0f; // If whole block is a hole, return as if there is no block here @@ -89,17 +206,17 @@ namespace BrewMonster.Scripts.World return 0.0f; // Get block's AABB - const A3DAABB&aabb = pBlock.GetBlockAABB(); + A3DAABB aabb = pBlock.GetBlockAABB(); // Get grid this position is in float fInvGridSize = 1.0f / m_fGridSize; iCol = (int)((vPos.x - aabb.Mins.x) * fInvGridSize); iRow = (int)(-(vPos.z - aabb.Maxs.z) * fInvGridSize); - a_Clamp(iCol, 0, m_iBlockGrid - 1); - a_Clamp(iRow, 0, m_iBlockGrid - 1); + AAssist.a_Clamp(ref iCol, 0, m_iBlockGrid - 1); + AAssist.a_Clamp(ref iRow, 0, m_iBlockGrid - 1); int iGrid = iRow * m_iBlockGrid + iCol; - const A3DTerrain2LOD::GRID&Grid = m_pLODMan.GetGrids()[iGrid]; + GRID Grid = m_pLODMan.GetGrids()[iGrid]; A3DVECTOR3 v0 = pBlock.GetVertexPos(Grid.v0); A3DVECTOR3 v1 = pBlock.GetVertexPos(Grid.v1); @@ -122,9 +239,9 @@ namespace BrewMonster.Scripts.World vDest = v5 + (v4 - v5) * (dx / (v4.x - v5.x)); vDest += (v3 - v4) * (dz / (v3.z - v4.z)); - if (pvNormal) + if (pvNormal != null) { - pvNormal.CrossProduct(v4 - v3, v5 - v3); + pvNormal = A3DVECTOR3.CrossProduct(v4 - v3, v5 - v3); pvNormal.Normalize(); } } @@ -133,9 +250,9 @@ namespace BrewMonster.Scripts.World vDest = v2 + (v0 - v2) * (dz / (v0.z - v2.z)); vDest += (v1 - v0) * (dx / (v1.x - v0.x)); - if (pvNormal) + if (pvNormal != null) { - pvNormal.CrossProduct(v1 - v0, v2 - v0); + pvNormal= A3DVECTOR3.CrossProduct(v1 - v0, v2 - v0); pvNormal.Normalize(); } } @@ -150,9 +267,9 @@ namespace BrewMonster.Scripts.World vDest = v0 + (v1 - v0) * (dx / (v1.x - v0.x)); vDest += (v2 - v1) * (dz / (v2.z - v1.z)); - if (pvNormal) + if (pvNormal != null) { - pvNormal.CrossProduct(v1 - v0, v2 - v0); + pvNormal = A3DVECTOR3.CrossProduct(v1 - v0, v2 - v0); pvNormal.Normalize(); } } @@ -161,9 +278,9 @@ namespace BrewMonster.Scripts.World vDest = v3 + (v5 - v3) * (dz / (v5.z - v3.z)); vDest += (v4 - v5) * (dx / (v4.x - v5.x)); - if (pvNormal) + if (pvNormal != null) { - pvNormal.CrossProduct(v4 - v3, v5 - v3); + pvNormal = A3DVECTOR3.CrossProduct(v4 - v3, v5 - v3); pvNormal.Normalize(); } } @@ -172,4 +289,62 @@ namespace BrewMonster.Scripts.World return vDest.y; } } + + // Active blocks + public struct ACTBLOCKS + { + public ARectI rcArea; // Active area represented in blocks + public BlockArray aBlocks; // Active block array + + public ACTBLOCKS(ARectI rcArea, BlockArray aBlocks) + { + this.rcArea = rcArea; + this.aBlocks = aBlocks; + } + + // Get block object at specified row, column. + public A3DTerrain2Block GetBlock(int r, int c, bool bClear) + { + //ASSERT(rcArea.PtInRect(c, r)); + + int iIndex = GetBlockIndex(r, c); + A3DTerrain2Block pBlock = aBlocks[iIndex]; + + if (bClear) + aBlocks[iIndex] = null; + + return pBlock; + } + + // Set block object at specified row, column + void SetBlock(int r, int c, A3DTerrain2Block pBlock) + { + //ASSERT(rcArea.PtInRect(c, r)); + int iIndex = GetBlockIndex(r, c); + aBlocks[iIndex] = pBlock; + } + + // Get block index in aBlocks + int GetBlockIndex(int r, int c) + { + return (r - rcArea.top) * rcArea.Width() + c - rcArea.left; + } + }; + + // Block flags & masks + public class Block_flags_masks + { + public static uint T2BKFLAG_DEFAULT = 0x00, // The block flag default value + T2BKFLAG_NORENDER = 0x01, // The whole block is not rendered + T2BKFLAG_NOTRACE = 0x02, // The whole block is out of RayTrace + T2BKFLAG_NOPOSHEIGHT = 0x04, // The whole block is unable to GetPosHeight + T2BKFLAG_NORENDERWITHWATER = 0x08; // The whole block is not rendered with water + }; + + // Vertex indices in a terrain grid + public struct GRID + { + public int v0, v1, v2; // Face 1 + public int v3, v4, v5; // Face 2 + }; } diff --git a/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs new file mode 100644 index 0000000000..6636b24e3b --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs @@ -0,0 +1,9 @@ +using BrewMonster.Scripts.World; +using UnityEngine; + +public class A3DTerrain2LOD +{ + public GRID[] m_aGrids; // Grid of a block + // Get grids + public GRID[] GetGrids() { return m_aGrids; } +} diff --git a/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs.meta b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs.meta new file mode 100644 index 0000000000..adced35aa5 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: ea4c2d97d77797548b9de5443e250290 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/ARect.cs b/Assets/PerfectWorld/Scripts/Managers/ARect.cs new file mode 100644 index 0000000000..4a13c814a9 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/ARect.cs @@ -0,0 +1,280 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace BrewMonster.Scripts +{ + public class ARect where T : IComparable + { + public T left, top, right, bottom; + + public ARect() + { + left = default(T); + top = default(T); + right = default(T); + bottom = default(T); + } + + public ARect(ARect rc) + { + left = rc.left; top = rc.top; right = rc.right; bottom = rc.bottom; + } + + public ARect(T left, T top, T right, T bottom) + { + this.left = left; + this.top = top; + this.right = right; + this.bottom = bottom; + } + + // == and != operator + public static bool operator !=(ARect rc1, ARect rc2) + { + return !(rc1 == rc2); + } + public static bool operator ==(ARect rc1, ARect rc2) + { + return EqualityComparer.Default.Equals(rc1.left, rc2.left) && + EqualityComparer.Default.Equals(rc1.top, rc2.top) && + EqualityComparer.Default.Equals(rc1.right, rc2.right) && + EqualityComparer.Default.Equals(rc1.bottom, rc2.bottom); + } + + // + and - operator + public static ARect operator +(ARect rc1, ARect rc2) + { + dynamic l = rc1.left, t = rc1.top, r = rc1.right, b = rc1.bottom; + dynamic l2 = rc2.left, t2 = rc2.top, r2 = rc2.right, b2 = rc2.bottom; + return new ARect(l + l2, t + t2, r + r2, b + b2); + } + public static ARect operator -(ARect rc1, ARect rc2) + { + return new ARect((dynamic)rc1.left - (dynamic)rc2.left, + (dynamic)rc1.top - (dynamic)rc2.top, + (dynamic)rc1.right - (dynamic)rc2.right, + (dynamic)rc1.bottom - (dynamic)rc2.bottom); + } + //public static ARect operator +(ARect rc1, APoint pt) + //{ + // return new ARect((dynamic)rc1.left + (dynamic)pt.x, + // (dynamic)rc1.top + (dynamic)pt.y, + // (dynamic)rc1.right + (dynamic)pt.x, + // (dynamic)rc1.bottom + (dynamic)pt.y); + //} + //public static ARect operator -(ARect rc1, APoint pt) + //{ + // return new ARect((dynamic)rc1.left - (dynamic)pt.x, + // (dynamic)rc1.top - (dynamic)pt.y, + // (dynamic)rc1.right - (dynamic)pt.x, + // (dynamic)rc1.bottom - (dynamic)pt.y); + //} + + // &= and |= operator + public ARect AndAssign(ARect rc) => this & rc; + public ARect OrAssign(ARect rc) => this | rc; + + public static ARect operator &(ARect rc1, ARect rc2) + { + if (rc1.IsEmpty() || rc2.IsEmpty()) + return new ARect(default, default, default, default); + + dynamic l1 = rc1.left, r1 = rc1.right, t1 = rc1.top, b1 = rc1.bottom; + dynamic l2 = rc2.left, r2 = rc2.right, t2 = rc2.top, b2 = rc2.bottom; + + if (l1 >= r2 || l2 >= r1 || + t1 >= b2 || t2 >= b1) + return new ARect(default, default, default, default); + + return new ARect(l1 > l2 ? l1 : l2, + t1 > t2 ? t1 : t2, + r1 < r2 ? r1 : r2, + b1 < b2 ? b1 : b2); + } + + public static ARect operator |(ARect rc1, ARect rc2) + { + if (rc1.IsEmpty()) + return rc2; + + if (rc2.IsEmpty()) + return rc1; + + dynamic l1 = rc1.left, r1 = rc1.right, t1 = rc1.top, b1 = rc1.bottom; + dynamic l2 = rc2.left, r2 = rc2.right, t2 = rc2.top, b2 = rc2.bottom; + + return new ARect(l1 < l2 ? l1 : l2, + t1 < t2 ? t1 : t2, + r1 > r2 ? r1 : r2, + b1 > b2 ? b1 : b2); + } + + public static ARect operator +(ARect rc) { return rc; } + public static ARect operator -(ARect rc) + { + return new ARect(-(dynamic)rc.left, -(dynamic)rc.top, -(dynamic)rc.right, -(dynamic)rc.bottom); + } + + // = operator + //public static ARect operator = (ARect rc) { left = rc.left; top = rc.top; right = rc.right; bottom = rc.bottom; return *this; } + + // += and -= operator + public ARect AdditionAssign(ARect rc) + { + left += (dynamic)rc.left; + top += (dynamic)rc.top; + right += (dynamic)rc.right; + bottom += (dynamic)rc.bottom; + return this; + } + public ARect SubtractionAssign(ARect rc) + { + left -= (dynamic)rc.left; + top -= (dynamic)rc.top; + right -= (dynamic)rc.right; + bottom -= (dynamic)rc.bottom; + return this; + } + //public ARect AdditionAssign(APoint pt) { left += pt.x; top += pt.y; right += pt.x; bottom += pt.y; return this; } + //public ARect SubtractionAssign(APoint pt) { left -= pt.x; top -= pt.y; right -= pt.x; bottom -= pt.y; return this; } + + // Get width of rectangle + public T Width() + { + return (dynamic)right - (dynamic)left; + } + // Get height of rectangle + public T Height() + { + return (dynamic)bottom - (dynamic)top; + } + // Get center point of rectangle + //public APoint CenterPoint() { return new APoint((left + right) / 2, (top + bottom) / 2); } + // Set rectangle value + public void SetRect(T _left, T _top, T _right, T _bottom) + { + left = _left; + top = _top; + right = _right; + bottom = _bottom; + } + + // Point in rectangle + public bool PtInRect(T x, T y) + { + dynamic valueX = x; + dynamic valueY = y; + return (valueX >= left && valueX < right && valueY >= top && valueY < bottom) ? true : false; + } + //public bool PtInRect(APoint pt) { return PtInRect(pt.x, pt.y); } + + // Normalize rectangle. Note: The following CRect member functions require + // normalized rectangles in order to work properly: Height, Width, Size, + // IsEmpty, PtInRect, SetUnion, SetIntersect, operator ==, operator !=, + // operator |, operator |=, operator &, and operator &= + void Normalize() + { + if ((dynamic)left > right) + a_Swap(left, right); + + if ((dynamic)top > bottom) + a_Swap(top, bottom); + } + + private void a_Swap(T lhs, T rhs) + { + T tmp; + tmp = lhs; + lhs = rhs; + rhs = tmp; + } + + // All members are 0 ? + public bool IsRectNull() + { + return ((dynamic)left == 0 && (dynamic)top == 0 && (dynamic)right == 0 && (dynamic)bottom == 0); + } + // Rectangle is empty ? + public bool IsEmpty() + { + return ((dynamic)Width() == 0 || (dynamic)Height() == 0); + } + // Set all members to 0 + public void Clear() + { + left = top = right = bottom = default(T); + } + // Deflate rectangle + public void Deflate(T x, T y) + { + left += (dynamic)x; + top += (dynamic)y; + right -= (dynamic)x; + bottom -= (dynamic)y; + } + public void Deflate(ARect rc) + { + left += (dynamic)rc.left; + top += (dynamic)rc.top; + right -= (dynamic)rc.right; + bottom -= (dynamic)rc.bottom; + } + public void Deflate(T l, T t, T r, T b) + { + left += (dynamic)l; + top += (dynamic)t; + right -= (dynamic)r; + bottom -= (dynamic)b; + } + // Inflate rectangle + public void Inflate(T x, T y) + { + left -= (dynamic)x; + top -= (dynamic)y; + right += (dynamic)x; + bottom += (dynamic)y; + } + public void Inflate(ARect rc) + { + left -= (dynamic)rc.left; + top -= (dynamic)rc.top; + right += (dynamic)rc.right; + bottom += (dynamic)rc.bottom; + } + public void Inflate(T l, T t, T r, T b) + { + left -= (dynamic)l; + top -= (dynamic)t; + right += (dynamic)r; + bottom += (dynamic)b; + } + // Offset rectangle + public void Offset(T x, T y) + { + left += (dynamic)x; + top += (dynamic)y; + right += (dynamic)x; + bottom += (dynamic)y; + } + //public void Offset(APoint pt) { this += pt; } + // Set rectangle as union result + public void SetUnion(ARect rc1, ARect rc2) + { + var result = rc1 | rc2; + left = result.left; + right = result.right; + bottom = result.bottom; + top = result.top; + } + // Set rectangle as intersect result + public void SetIntersect(ARect rc1, ARect rc2) + { + var result = rc1 & rc2; + left = result.left; + right = result.right; + bottom = result.bottom; + top = result.top; + } + } +} diff --git a/Assets/PerfectWorld/Scripts/Managers/ARect.cs.meta b/Assets/PerfectWorld/Scripts/Managers/ARect.cs.meta new file mode 100644 index 0000000000..66c5766867 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/ARect.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 00eedf309b0008346a58412f4aad4dec \ No newline at end of file diff --git a/Assets/Scripts/Move/EC_CDR.cs b/Assets/Scripts/Move/EC_CDR.cs index 4b7b0506ca..5d91a37209 100644 --- a/Assets/Scripts/Move/EC_CDR.cs +++ b/Assets/Scripts/Move/EC_CDR.cs @@ -1,6 +1,8 @@ -using CSNetwork.GPDataType; -using UnityEditor.PackageManager; +using BrewMonster.Scripts.World; +using CSNetwork.GPDataType; +using System; using UnityEngine; +using WORD = System.UInt16; namespace BrewMonster.Scripts { @@ -312,38 +314,37 @@ namespace BrewMonster.Scripts bool CollideWithTerrain(A3DVECTOR3 vStart, A3DVECTOR3 vDelta, ref float fFraction, ref A3DVECTOR3 vHitNormal, ref bool bStart) { - CECWorld pWorld = g_pGame.GetGameRun().GetWorld(); - A3DTerrain2 pTerrain = pWorld.GetTerrain(); - bStart = false; - float h1 = pTerrain.GetPosHeight(vStart, &vHitNormal); - if (h1 > vStart.y + 1E-4f ) - {//start under terrain - bStart = true; - fFraction = 0.0f; - return true; - } + CECWorld pWorld = CECWorld.Instance; //g_pGame.GetGameRun().GetWorld(); + A3DTerrain2 pTerrain = pWorld.GetTerrain(); + bStart = false; + float h1 = pTerrain.GetPosHeight(vStart, ref vHitNormal); + if (h1 > vStart.y + 1E-4f ) + {//start under terrain + bStart = true; + fFraction = 0.0f; + return true; + } + int nWid, nHei; // in grid, 2 meters + float fMag = vDelta.Magnitude(); - int nWid, nHei; // in grid, 2 meters - float fMag = vDelta.Magnitude(); - - nWid = (int) ceil(fMag / 2.0f); - nWid = a_Max(3, nWid); - nHei = nWid; - int nTriangles = nWid * nHei * 2; - A3DVECTOR3* pVerts = (A3DVECTOR3*)a_malloctemp(sizeof(A3DVECTOR3) * ((nWid + 1) * (nHei + 1))); - assert(pVerts != NULL); - memset(pVerts, 0, sizeof(A3DVECTOR3)* (nWid + 1) * (nHei + 1)); - WORD* pIndices = (WORD*)a_malloctemp(sizeof(WORD) * (nTriangles * 3)); - assert(pIndices != NULL); - memset(pIndices, 0, sizeof(WORD)* nTriangles * 3); - if (!pTerrain.GetFacesOfArea(vStart, nWid, nHei, pVerts, pIndices)) - { - a_freetemp(pVerts); - a_freetemp(pIndices); - return false; - } -int i; + nWid = (int)Math.Ceiling(fMag / 2.0f); + nWid = Math.Max(3, nWid); + nHei = nWid; + int nTriangles = nWid * nHei * 2; + A3DVECTOR3[] pVerts = new A3DVECTOR3[(nWid + 1) * (nHei + 1)]; + //assert(pVerts != NULL); + //memset(pVerts, 0, sizeof(A3DVECTOR3)* (nWid + 1) * (nHei + 1)); + WORD[] pIndices = new WORD[nTriangles * 3]; + //assert(pIndices != NULL); + //memset(pIndices, 0, sizeof(WORD)* nTriangles * 3); + if (!pTerrain.GetFacesOfArea(vStart, nWid, nHei, pVerts, pIndices)) + { + //a_freetemp(pVerts); + // a_freetemp(pIndices); + return false; + } + int i; A3DVECTOR3* vert[3]; //@note : Here init the fraction. By Kuiwu[9/10/2005] fFraction = 100.0f; @@ -384,26 +385,6 @@ fFraction = a_Max(0.0f, tmpFraction); a_freetemp(pVerts); a_freetemp(pIndices); -# ifdef CDR_DEBUG -// if (fFraction <= 1.0f) -// { -// A3DVECTOR3 vHitPos(vStart + vDelta * fFraction); -// A3DVECTOR3 vTerNormal; -// float fH2 = pTerrain.GetPosHeight(vHitPos, &vTerNormal); -// sprintf(msg, "terrain hit %f %f %f normal %f %f %f trcNormal %f %f %f fFraction %f\n", vHitPos.x, vHitPos.y, vHitPos.z, -// vHitNormal.x, vHitNormal.y, vHitNormal.z, vTerNormal.x, vTerNormal.y, vTerNormal.z, fFraction); -// OUTPUT_DEBUG_INFO(msg); -// -// //vHitNormal = vTerNormal; -// } -// else -// { -// A3DVECTOR3 vEnd(vStart + vDelta); -// float fH2 = pTerrain.GetPosHeight(vEnd); -// sprintf(msg, "terrain test clear %f %f %f height %f\n", vEnd.x, vEnd.y, vEnd.z,fH2); -// OUTPUT_DEBUG_INFO(msg); -// } -#endif return (fFraction <= 1.0f); }