public bool Intersect(IntersectionParams parameters, ref Ray globalRay, out float distance, out WmoInstance instance) { distance = float.MaxValue; instance = null; if (mInstances == null) { return(false); } lock (mInstances) { foreach (var inst in mInstances.Values) { float dist; if (inst.Intersects(parameters, ref globalRay, out dist) && dist < distance) { distance = dist; instance = inst; } } } return(instance != null); }
private void OnWorldClick(IntersectionParams intersectionParams, MouseEventArgs args) { if (args.Button != MouseButtons.Left) { return; } var keys = new byte[256]; UnsafeNativeMethods.GetKeyboardState(keys); if (KeyHelper.IsKeyDown(keys, Keys.ControlKey) || KeyHelper.IsKeyDown(keys, Keys.ShiftKey)) { return; } if (intersectionParams.ChunkHit == null) { mLastArea = null; return; } MapArea area; if (intersectionParams.ChunkHit.Parent.TryGetTarget(out area) == false) { return; } var updateArea = true; if (mLastArea != null) { MapArea lastArea; if (mLastArea.TryGetTarget(out lastArea) && lastArea == area) { updateArea = false; } } mLastArea = intersectionParams.ChunkHit.Parent; if (updateArea) { SetSelectedTileTextures(mWidget.SelectedTileWrapPanel, area.TextureNames); } MapChunk lastChunk; if (mLastChunk != null && mLastChunk.TryGetTarget(out lastChunk)) { if (lastChunk == intersectionParams.ChunkHit) { return; } } mLastChunk = new WeakReference <MapChunk>(intersectionParams.ChunkHit); SetSelectedTileTextures(mWidget.SelectedChunkWrapPanel, intersectionParams.ChunkHit.TextureNames); }
public bool Intersects(IntersectionParams parameters, ref Ray globalRay, out float value) { value = float.MaxValue; if (globalRay.Intersects(ref mBoundingBox) == false) { return(false); } var instRay = Picking.Build(ref parameters.ScreenPosition, ref parameters.InverseView, ref parameters.InverseProjection, ref mInverseMatrix); return(mModel.Intersect(ref instRay, out value)); }
public void OnTerrainClicked(IntersectionParams parameters, MouseEventArgs args) { if (EditManager.Instance.CurrentMode == EditMode.Chunk) { return; } if (args.Button != MouseButtons.Left) { if (args.Button == MouseButtons.Right) { var state = new byte[256]; UnsafeNativeMethods.GetKeyboardState(state); if (KeyHelper.IsKeyDown(state, Keys.ControlKey)) { WorldFrame.Instance.M2Manager.RemoveInstance(mSelectedModel, M2InstanceUuid); mHoveredInstance = null; mSelectedModel = null; WorldFrame.Instance.OnWorldClicked -= OnTerrainClicked; } } ModelEditManager.Instance.IsCopying = false; return; } if (parameters.TerrainHit == false) { return; } if (mHoveredInstance == null) { return; } SpawnModel(parameters.TerrainPosition); ModelEditManager.Instance.IsCopying = !EditorWindowController.Instance.SpawnModel.DeselectModelOnClick; if (!ModelEditManager.Instance.IsCopying) { WorldFrame.Instance.M2Manager.RemoveInstance(mSelectedModel, M2InstanceUuid); mHoveredInstance = null; mSelectedModel = null; WorldFrame.Instance.OnWorldClicked -= OnTerrainClicked; } }
public void Intersect(IntersectionParams parameters) { var ray = Picking.Build(ref parameters.ScreenPosition, ref parameters.InverseView, ref parameters.InverseProjection); var hasHit = false; var minDist = float.MaxValue; MapChunk chunkHit = null; // ReSharper disable once InconsistentlySynchronizedField foreach (var pair in mAreas) { MapChunk chunk; float distance; if (!pair.Value.AreaFile.Intersect(ref ray, out chunk, out distance)) { continue; } hasHit = true; if ((distance >= minDist)) { continue; } minDist = distance; chunkHit = chunk; } parameters.TerrainHit = hasHit; if (hasHit) { parameters.TerrainPosition = ray.Position + minDist * ray.Direction; parameters.TerrainDistance = minDist; } else { parameters.TerrainPosition = new Vector3(float.MaxValue); } parameters.ChunkHit = chunkHit; }
public override void SetHole(IntersectionParams intersection, bool add) { float holesize = CHUNKSIZE / 4.0f; var min = BoundingBox.Minimum; var intersect = new Vector2(intersection.TerrainPosition.X, intersection.TerrainPosition.Y); for (int x = 0; x < 4; x++) { for (int y = 0; y < 4; y++) { RectangleF bounds = new RectangleF ( min.X + (x * holesize), min.Y + (y * holesize), holesize, holesize ); if (bounds.Contains(intersect)) { var baseIndex = y * 2 * 8 + x * 2; int bit = (1 << (y * 4 + x)); if (add) { mHeader.Holes |= bit; } else { mHeader.Holes &= ~bit; } HoleValues[baseIndex] = HoleValues[baseIndex + 1] = HoleValues[baseIndex + 8] = HoleValues[baseIndex + 9] = (byte)(add ? 0x00 : 0xFF); return; } } } }
public void Intersect(IntersectionParams parameters) { if (mRenderer == null) { return; } var globalRay = Picking.Build(ref parameters.ScreenPosition, ref parameters.InverseView, ref parameters.InverseProjection); var minDistance = float.MaxValue; WmoInstance wmoHit = null; lock (mRenderer) { foreach (var renderer in mRenderer) { WmoInstance hit; float distance; if (renderer.Value.Intersect(parameters, ref globalRay, out distance, out hit) && distance < minDistance) { minDistance = distance; wmoHit = hit; } } } if (wmoHit != null) { parameters.WmoHit = true; parameters.WmoInstance = wmoHit; parameters.WmoModel = wmoHit.ModelRoot; parameters.WmoPosition = globalRay.Position + minDistance * globalRay.Direction; parameters.WmoDistance = minDistance; } else { parameters.WmoHit = false; } }
public bool Intersects(IntersectionParams parameters, ref Ray globalRay, out float distance) { distance = float.MaxValue; if (globalRay.Intersects(ref BoundingBox) == false) { return(false); } WmoRootRender renderer; if (mRenderer.TryGetTarget(out renderer) == false) { return(false); } var instRay = Picking.Build(ref parameters.ScreenPosition, ref parameters.InverseView, ref parameters.InverseProjection, ref mInverseInstanceMatrix); var hasHit = false; for (var i = 0; i < GroupBoxes.Length; ++i) { if (globalRay.Intersects(ref GroupBoxes[i]) == false) { continue; } float dist; if (renderer.Groups[i].Intersects(parameters, ref instRay, out dist) && dist < distance) { distance = dist; hasHit = true; } } return(hasHit); }
public override void SetHole(IntersectionParams intersection, bool add) { float holesize = CHUNKSIZE / 4.0f; var min = BoundingBox.Minimum; var intersect = new Vector2(intersection.TerrainPosition.X, intersection.TerrainPosition.Y); bool use64bit = (mHeader.Flags & 0x10000) == 0x10000; if (!use64bit) { for (int x = 0; x < 4; x++) { for (int y = 0; y < 4; y++) { RectangleF bounds = new RectangleF ( min.X + (x * holesize), min.Y + (y * holesize), holesize, holesize ); if (bounds.Contains(intersect)) { y = 3 - y; //Inverse var baseIndex = y * 2 * 8 + x * 2; int bit = (1 << (y * 4 + x)); if (add) { mHeader.Holes |= bit; } else { mHeader.Holes &= ~bit; } HoleValues[baseIndex] = HoleValues[baseIndex + 1] = HoleValues[baseIndex + 8] = HoleValues[baseIndex + 9] = (byte)(add ? 0x00 : 0xFF); return; } } } } else { holesize = CHUNKSIZE / 8.0f; var holeBytes = new byte[8]; Buffer.BlockCopy(BitConverter.GetBytes(mHeader.Mcvt), 0, holeBytes, 0, 4); Buffer.BlockCopy(BitConverter.GetBytes(mHeader.Mcnr), 0, holeBytes, 4, 4); for (var x = 0; x < 8; ++x) { for (var y = 0; y < 8; ++y) { RectangleF bounds = new RectangleF ( min.X + (x * holesize), min.Y + (y * holesize), holesize, holesize ); if (bounds.Contains(intersect)) { y = (7 - y); //Inverse byte bit = (byte)(1 << x); if (add) { holeBytes[y] |= bit; } else { holeBytes[y] = (byte)(holeBytes[y] & ~bit); } mHeader.Mcvt = BitConverter.ToInt32(holeBytes, 0); mHeader.Mcnr = BitConverter.ToInt32(holeBytes, 4); int h = y * 8 + x; HoleValues[h] = (byte)(add ? 0x00 : 0xFF); return; } } } } }
private void OnChunkClicked(IntersectionParams intersection, MouseEventArgs e) { var chunk = mHoveredChunk; var keyState = new byte[256]; UnsafeNativeMethods.GetKeyboardState(keyState); MapArea parent; switch (ChunkEditMode) { case ChunkEditMode.AreaPaint: if (SelectedAreaId == 0 || !KeyHelper.IsKeyDown(keyState, Keys.LButton)) { return; } if (chunk.Parent.TryGetTarget(out parent)) { chunk.AreaId = SelectedAreaId; parent.SetChanged(); ForceRenderUpdate?.Invoke(chunk, false); } break; case ChunkEditMode.AreaSelect: if (!KeyHelper.IsKeyDown(keyState, Keys.LButton)) { return; } SelectedAreaId = chunk.AreaId; SelectedAreaIdChange?.Invoke(SelectedAreaId); break; case ChunkEditMode.Hole: if (!KeyHelper.IsKeyDown(keyState, Keys.LButton)) { return; } if (chunk.Parent.TryGetTarget(out parent)) { if (SmallHole) { chunk.SetHole(intersection, AddHole); } else { chunk.SetHoleBig(AddHole); } parent.SetChanged(); ForceRenderUpdate?.Invoke(chunk, true); } break; case ChunkEditMode.Flags: if (!KeyHelper.IsKeyDown(keyState, Keys.LButton)) { return; } if (chunk.Parent.TryGetTarget(out parent)) { if (chunk.HasImpassFlag) { chunk.Flags &= ~0x2u; } else { chunk.Flags |= 0x2; } parent.SetChanged(); ForceRenderUpdate?.Invoke(chunk, false); } break; } }
public abstract void SetHole(IntersectionParams intersection, bool add);
public void Intersect(IntersectionParams parameters) { if (mVisibleInstances == null || mNonBatchedInstances == null || mSortedInstances == null) { return; } var globalRay = Picking.Build(ref parameters.ScreenPosition, ref parameters.InverseView, ref parameters.InverseProjection); var minDistance = float.MaxValue; M2RenderInstance selectedInstance = null; lock (mVisibleInstances) { foreach (var pair in mVisibleInstances) { if (pair.Value.Uuid == Editing.ModelSpawnManager.M2InstanceUuid) { continue; } float dist; if (pair.Value.Intersects(parameters, ref globalRay, out dist) && dist < minDistance) { minDistance = dist; selectedInstance = pair.Value; } } } lock (mNonBatchedInstances) { foreach (var pair in mNonBatchedInstances) { float dist; if (pair.Value.Intersects(parameters, ref globalRay, out dist) && dist < minDistance) { minDistance = dist; selectedInstance = pair.Value; } } } lock (mSortedInstances) { foreach (var pair in mSortedInstances) { float dist; if (pair.Value.Intersects(parameters, ref globalRay, out dist) && dist < minDistance) { minDistance = dist; selectedInstance = pair.Value; } } } if (selectedInstance != null) { parameters.M2Instance = selectedInstance; parameters.M2Model = selectedInstance.Model; parameters.M2Position = globalRay.Position + minDistance * globalRay.Direction; parameters.M2Distance = minDistance; } parameters.M2Hit = selectedInstance != null; }
public bool Intersects(IntersectionParams parameters, ref Ray ray, out float distance) { distance = float.MaxValue; var hasHit = false; var orig = ray.Position; var dir = ray.Direction; Vector3 e1, e2, p, T, q; foreach (var batch in mBatches) { for (int i = batch.Batch.StartIndex, j = 0; j < batch.Batch.NumIndices; i += 3, j += 3) { var i0 = Data.Indices[i]; var i1 = Data.Indices[i + 1]; var i2 = Data.Indices[i + 2]; Vector3.Subtract(ref Data.Vertices[i1].Position, ref Data.Vertices[i0].Position, out e1); Vector3.Subtract(ref Data.Vertices[i2].Position, ref Data.Vertices[i0].Position, out e2); Vector3.Cross(ref dir, ref e2, out p); float det; Vector3.Dot(ref e1, ref p, out det); if (Math.Abs(det) < 1e-4) { continue; } var invDet = 1.0f / det; Vector3.Subtract(ref orig, ref Data.Vertices[i0].Position, out T); float u; Vector3.Dot(ref T, ref p, out u); u *= invDet; if (u < 0 || u > 1) { continue; } Vector3.Cross(ref T, ref e1, out q); float v; Vector3.Dot(ref dir, ref q, out v); v *= invDet; if (v < 0 || (u + v) > 1) { continue; } float t; Vector3.Dot(ref e2, ref q, out t); t *= invDet; if (t < 1e-4) { continue; } hasHit = true; if (t < distance) { distance = t; } } } return(hasHit); }
public void Intersect(IntersectionParams parameters) { var ray = Picking.Build(ref parameters.ScreenPosition, ref parameters.InverseView, ref parameters.InverseProjection); var hasHit = false; var minDist = float.MaxValue; MapChunk chunkHit = null; // ReSharper disable once InconsistentlySynchronizedField foreach(var pair in mAreas) { MapChunk chunk; float distance; if (!pair.Value.AreaFile.Intersect(ref ray, out chunk, out distance)) continue; hasHit = true; if ((distance >= minDist)) continue; minDist = distance; chunkHit = chunk; } parameters.TerrainHit = hasHit; if (hasHit) parameters.TerrainPosition = ray.Position + minDist * ray.Direction; else parameters.TerrainPosition = new Vector3(float.MaxValue); parameters.ChunkHit = chunkHit; }