private static VertexState ConvertToVertexBuffer(ModelPrimitive.VerticesList vlist, Device device) { var vertexElems = new[] { new VertexElement(0, 0, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Position, 0), new VertexElement(0, 12, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Normal, 0), new VertexElement(0, 24, DeclarationType.Float2, DeclarationMethod.Default, DeclarationUsage.TextureCoordinate, 0), new VertexElement(0, 32, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Tangent, 0), new VertexElement(0, 44, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Binormal, 0), VertexElement.VertexDeclarationEnd }; var vertexSize = 56; var vertexBuffer = new VertexBuffer(device, vertexSize * vlist.Vertices.Count, Usage.WriteOnly, VertexFormat.None, Pool.Default); var data = vertexBuffer.Lock(0, 0, LockFlags.None); foreach (var v in vlist.Vertices) { data.Write(DXUtils.Convert(v.Position)); data.Write(DXUtils.Convert(v.Normal)); data.Write(DXUtils.Convert(v.TextureCoordinates)); data.Write(DXUtils.Convert(v.Tangent)); data.Write(DXUtils.Convert(v.Binormal)); } var vertexDecl = new VertexDeclaration(device, vertexElems); vertexBuffer.Unlock(); return(new VertexState() { VertexBuffer = vertexBuffer, VertexDeclaration = vertexDecl, Stride = vertexSize, Count = vlist.Vertices.Count }); }
public ShootTestResult GetShootTestResult(TestShellInfo testShell) { PenetrationState penetrationState = PenetrationState.NotApplicable; double equivalentThickness = 0.0; double impactAngle = 0.0; double nomarlizationAngle = 0.0; bool is2x = false; bool is3x = false; bool mayRicochet = true; bool heatExploded = false; double heatExplodedDistance = 0.0; bool isFirstHit = true; var orderedHits = Hits.OrderBy((h) => h.Distance); foreach (var hit in orderedHits) { var thisImpactAngle = DXUtils.ConvertRadiansToDegrees(Math.Acos(hit.InjectionCosine)); if (isFirstHit) { impactAngle = thisImpactAngle; } if (hit.Armor.UseHitAngle && hit.Armor.Thickness != 0.0) { mayRicochet = mayRicochet && hit.Armor.MayRicochet; double thisNomarlizationAngle = testShell.ShellType.GetBaseNormalization(); if (testShell.Caliber >= hit.Armor.Thickness * 3.0 && testShell.ShellType.HasNormalizationEffect()) { is3x = true; is2x = true; mayRicochet = false; thisNomarlizationAngle *= 1.4 * testShell.Caliber / hit.Armor.Thickness; } else if (testShell.Caliber >= hit.Armor.Thickness * 2.0 && testShell.ShellType.HasNormalizationEffect()) { is3x = false; is2x = testShell.ShellType.HasNormalizationEffect(); thisNomarlizationAngle *= 1.4 * testShell.Caliber / hit.Armor.Thickness; } if (mayRicochet && thisImpactAngle > testShell.ShellType.GetRicochetAngle()) { penetrationState = PenetrationState.Richochet; break; } if (isFirstHit && testShell.ShellType.HasNormalizationEffect()) { if (thisNomarlizationAngle > thisImpactAngle) { thisNomarlizationAngle = thisImpactAngle; } thisImpactAngle -= thisNomarlizationAngle; nomarlizationAngle = thisNomarlizationAngle; } if (!heatExploded) { equivalentThickness += hit.Armor.Thickness / Math.Cos(DXUtils.ConvertDegreesToRadians(thisImpactAngle)); } else { var distance = (hit.Distance - heatExplodedDistance); var attenuation = 1 - distance * 0.5; if (attenuation < 0) { penetrationState = PenetrationState.Unpenetratable; break; } equivalentThickness += hit.Armor.Thickness / attenuation / Math.Cos(DXUtils.ConvertDegreesToRadians(thisImpactAngle)); } } else { if (!heatExploded) { equivalentThickness += hit.Armor.Thickness; } else { var distance = (hit.Distance - heatExplodedDistance); var attenuation = 1 - distance * 0.5; if (attenuation < 0) { penetrationState = PenetrationState.Unpenetratable; break; } equivalentThickness += hit.Armor.Thickness / attenuation; } } if (!hit.Armor.IsSpacedArmor) { if (equivalentThickness < 999.0) { penetrationState = PenetrationState.Penetratable; } else { penetrationState = PenetrationState.Unpenetratable; } break; } else { if (testShell.ShellType == ShellType.HE || testShell.ShellType == ShellType.PremiumHE) { penetrationState = PenetrationState.Unpenetratable; break; } else if (testShell.ShellType == ShellType.HEAT && isFirstHit) { heatExploded = true; heatExplodedDistance = hit.Distance; mayRicochet = false; } } isFirstHit = false; } return(new ShootTestResult(penetrationState, equivalentThickness, impactAngle, nomarlizationAngle, is2x, is3x)); }
public void Refresh(TestShellInfo testShell) { this.LogInfo("refresh"); _tracerLines = new List <TracerLineVertex>(); _tracerLines.Add(new TracerLineVertex() { Position = _tracerRay.Position, Penetration = 0 }); PenetrationState penetrationState = PenetrationState.NotApplicable; bool mayRicochet = true; float equivalentThickness = 0.0f; float heatExplodedDistance = 0.0f; bool heatExploded = false; foreach (var hit in _orderedHits) { _hitMeshs.Add(hit.Mesh); if (!heatExploded) { _tracerLines.Add(new TracerLineVertex() { Position = _tracerRay.Position + hit.Distance * _tracerRay.Direction, Penetration = equivalentThickness }); } var thisImpactAngle = DXUtils.ConvertRadiansToDegrees(Math.Acos(hit.InjectionCosine)); if (hit.Armor.UseHitAngle && hit.Armor.Thickness != 0.0) { mayRicochet = mayRicochet && hit.Armor.MayRicochet; double thisNomarlizationAngle = testShell.ShellType.GetBaseNormalization(); if (testShell.Caliber >= hit.Armor.Thickness * 3.0) { mayRicochet = false; thisNomarlizationAngle *= 1.4 * testShell.Caliber / hit.Armor.Thickness; } else if (testShell.Caliber >= hit.Armor.Thickness * 2.0) { thisNomarlizationAngle *= 1.4 * testShell.Caliber / hit.Armor.Thickness; } if (mayRicochet && thisImpactAngle > testShell.ShellType.GetRicochetAngle()) { penetrationState = PenetrationState.Richochet; break; } if (testShell.ShellType.HasNormalizationEffect()) { if (thisNomarlizationAngle > thisImpactAngle) { thisNomarlizationAngle = thisImpactAngle; } thisImpactAngle -= thisNomarlizationAngle; } if (!heatExploded) { equivalentThickness += (float)(hit.Armor.Thickness / Math.Cos(DXUtils.ConvertDegreesToRadians(thisImpactAngle))); } else { var distance = (hit.Distance - heatExplodedDistance); var attenuation = 1 - distance * 0.5; if (attenuation < 0) { _tracerLines.Add(new TracerLineVertex() { Position = _tracerRay.Position + hit.Distance * _tracerRay.Direction, Penetration = 0 }); penetrationState = PenetrationState.Unpenetratable; break; } equivalentThickness += (float)(hit.Armor.Thickness / attenuation / Math.Cos(DXUtils.ConvertDegreesToRadians(thisImpactAngle))); _tracerLines.Add(new TracerLineVertex() { Position = _tracerRay.Position + hit.Distance * _tracerRay.Direction, Penetration = equivalentThickness }); } } else { if (!heatExploded) { equivalentThickness += (float)hit.Armor.Thickness; } else { var distance = (hit.Distance - heatExplodedDistance); var attenuation = 1 - distance * 0.5; if (attenuation < 0) { _tracerLines.Add(new TracerLineVertex() { Position = _tracerRay.Position + hit.Distance * _tracerRay.Direction, Penetration = 0 }); penetrationState = PenetrationState.Unpenetratable; break; } equivalentThickness += (float)(hit.Armor.Thickness / attenuation); _tracerLines.Add(new TracerLineVertex() { Position = _tracerRay.Position + hit.Distance * _tracerRay.Direction, Penetration = equivalentThickness }); } } if (!hit.Armor.IsSpacedArmor) { penetrationState = PenetrationState.Penetratable; break; } else { if (testShell.ShellType == ShellType.HE || testShell.ShellType == ShellType.PremiumHE) { penetrationState = PenetrationState.Unpenetratable; break; } else if (testShell.ShellType == ShellType.HEAT && !heatExploded) { heatExploded = true; heatExplodedDistance = hit.Distance; mayRicochet = false; } } _tracerLines.Add(new TracerLineVertex() { Position = _tracerRay.Position + hit.Distance * _tracerRay.Direction, Penetration = equivalentThickness }); } if (penetrationState == PenetrationState.Penetratable) { for (int i = 0; i != _tracerLines.Count; ++i) { _tracerLines[i] = new TracerLineVertex() { Position = _tracerLines[i].Position, Penetration = (equivalentThickness - _tracerLines[i].Penetration) * 0.5f }; } } else if (penetrationState == PenetrationState.Richochet || penetrationState == PenetrationState.Unpenetratable || penetrationState == PenetrationState.NotApplicable) { for (int i = 0; i != _tracerLines.Count; ++i) { _tracerLines[i] = new TracerLineVertex() { Position = _tracerLines[i].Position, Penetration = -1.0f }; } } BuildCollision(); }