public static void WpfColorFromColor4(ref Color4 source, ref WpfMedia.Color target) { target.A = (byte)EngineMath.Clamp(0f, 255f, source.Alpha * 255f); target.R = (byte)EngineMath.Clamp(0f, 255f, source.Alpha * 255f); target.G = (byte)EngineMath.Clamp(0f, 255f, source.Alpha * 255f); target.B = (byte)EngineMath.Clamp(0f, 255f, source.Alpha * 255f); }
/// <summary> /// Builds a geosphere geometry. /// </summary> public static BuiltVerticesRange BuildGeosphere(this GeometrySurface target, float radius, int countSubdivisions) { // Implemented with sample code from http://www.d3dcoder.net/d3d11.htm, Source Code Set II countSubdivisions = Math.Max(countSubdivisions, 0); radius = Math.Max(Math.Abs(radius), EngineMath.TOLERANCE_FLOAT_POSITIVE); // <-- this one prevents device by zero var startVertex = target.Owner.CountVertices; var startTriangle = target.Owner.CountTriangles; // Build an icosahedron const float X = 0.525731f; const float Z = 0.850651f; var pos = new[] { new Vector3(-X, 0f, Z), new Vector3(X, 0f, Z), new Vector3(-X, 0f, -Z), new Vector3(X, 0f, -Z), new Vector3(0f, Z, X), new Vector3(0f, Z, -X), new Vector3(0f, -Z, X), new Vector3(0f, -Z, -X), new Vector3(Z, X, 0f), new Vector3(-Z, X, 0f), new Vector3(Z, -X, 0f), new Vector3(-Z, -X, 0f) }; var k = new[] { 1, 4, 0, 4, 9, 0, 4, 5, 9, 8, 5, 4, 1, 8, 4, 1, 10, 8, 10, 3, 8, 8, 3, 5, 3, 2, 5, 3, 7, 2, 3, 10, 7, 10, 6, 7, 6, 11, 7, 6, 0, 11, 6, 1, 0, 10, 1, 6, 11, 0, 9, 2, 11, 9, 5, 2, 9, 11, 2, 7 }; foreach (var actPosition in pos) { target.Owner.AddVertex(new VertexBasic(actPosition)); } for (var loop = 0; loop < k.Length; loop += 3) { target.AddTriangle(k[loop], k[loop + 1], k[loop + 2]); } // Subdivide it n times for (var loop = 0; loop < countSubdivisions; loop++) { target.Subdivide(startTriangle); } // Project vertices onto sphere and scale var vertexCount = target.Owner.CountVertices; for (var actVertexIndex = startVertex; actVertexIndex < vertexCount; actVertexIndex++) { ref var actVertex = ref target.Owner.GetVertexBasicRef(actVertexIndex); actVertex.Normal = Vector3.Normalize(actVertex.Position); actVertex.Position = actVertex.Normal * radius; var theta = EngineMath.AngleFromXY(actVertex.Position.X, actVertex.Position.Z); var phi = (float)Math.Acos(actVertex.Position.Y / radius); actVertex.TexCoord1 = new Vector2( theta / EngineMath.PI_2, phi / EngineMath.PI); }
public void BitmapComparison_Positive() { using (var leftBitmap = TestUtilities.LoadBitmapFromResource("BitmapComparison", "FlatShadedObject.png")) using (var rightBitmap = TestUtilities.LoadBitmapFromResource("BitmapComparison", "FlatShadedObject.png")) { Assert.IsTrue( EngineMath.EqualsWithTolerance(BitmapComparison.CalculatePercentageDifference(leftBitmap, rightBitmap), 0f)); } }
public void BitmapComparison_Negative_BlackWhite() { using (var leftBitmap = TestUtilities.LoadBitmapFromResource("BitmapComparison", "WhiteScreen.png")) using (var rightBitmap = TestUtilities.LoadBitmapFromResource("BitmapComparison", "BlackScreen.png")) { var comparisonResult = BitmapComparison.CalculatePercentageDifference(leftBitmap, rightBitmap); Assert.IsTrue(EngineMath.EqualsWithTolerance(comparisonResult, 1.0f)); } }
static public Color ParseColor24(string text, int offset) { int r = (EngineMath.HexToDecimal(text[offset]) << 4) | EngineMath.HexToDecimal(text[offset + 1]); int g = (EngineMath.HexToDecimal(text[offset + 2]) << 4) | EngineMath.HexToDecimal(text[offset + 3]); int b = (EngineMath.HexToDecimal(text[offset + 4]) << 4) | EngineMath.HexToDecimal(text[offset + 5]); float f = 1f / 255f; return(new Color(f * r, f * g, f * b)); }
public static Color UIColorFromColor4(ref Color4 color) { var uiColor = new Color { A = (byte)EngineMath.Clamp(0f, 255f, color.Alpha * 255f), R = (byte)EngineMath.Clamp(0f, 255f, color.Red * 255f), G = (byte)EngineMath.Clamp(0f, 255f, color.Green * 255f), B = (byte)EngineMath.Clamp(0f, 255f, color.Blue * 255f) }; return(uiColor); }
public static void EnsureNormalized( this Vector2 vectorValue, string checkedVariableName, [CallerMemberName] string callerMethod = "") { if (string.IsNullOrEmpty(callerMethod)) { callerMethod = "Unknown"; } if (!EngineMath.EqualsWithTolerance(vectorValue.Length(), 1f)) { throw new SeeingSharpCheckException(string.Format( "Vector {0} within method {1} must be normalized!", checkedVariableName, callerMethod, vectorValue)); } }
public static void EnsureNotEqual( this Vector2 vectorValueLeft, Vector2 vectorValueRight, string checkedVariableName, string comparedVariableName, [CallerMemberName] string callerMethod = "") { if (string.IsNullOrEmpty(callerMethod)) { callerMethod = "Unknown"; } if (EngineMath.EqualsWithTolerance(vectorValueLeft.X, vectorValueRight.X) && EngineMath.EqualsWithTolerance(vectorValueLeft.Y, vectorValueRight.Y)) { throw new SeeingSharpCheckException( $"Vector {checkedVariableName} within method {callerMethod} with value {vectorValueLeft} musst not be equal with the vector {comparedVariableName}!"); } }
/// <summary> /// Sets current transform settings on this graphics object. /// (be careful, the state is changed on device level!) /// </summary> /// <param name="transformSettings">The settings to be set.</param> internal void PushTransformSettings(Graphics2DTransformSettings transformSettings) { _transformSettings = transformSettings; switch (transformSettings.TransformMode) { // Overtake given scaling matrix case Graphics2DTransformMode.Custom: this.TransformStack.Push(transformSettings.CustomTransform); break; // Calculate scaling matrix here case Graphics2DTransformMode.AutoScaleToVirtualScreen: var virtualWidth = _transformSettings.VirtualScreenSize.Width; var virtualHeight = _transformSettings.VirtualScreenSize.Height; if (EngineMath.EqualsWithTolerance(virtualWidth, 0f)) { virtualWidth = this.ScreenPixelSize.Width; } if (EngineMath.EqualsWithTolerance(virtualHeight, 0f)) { virtualHeight = this.ScreenPixelSize.Height; } var scaleFactorX = this.ScreenPixelSize.Width / virtualWidth; var scaleFactorY = this.ScreenPixelSize.Height / virtualHeight; var combinedScaleFactor = Math.Min(scaleFactorX, scaleFactorY); var truePixelWidth = virtualWidth * combinedScaleFactor; var truePixelHeight = virtualHeight * combinedScaleFactor; this.TransformStack.Push(); this.TransformStack.TransformLocal( Matrix3x2.CreateScale(combinedScaleFactor) * Matrix3x2.CreateTranslation(this.ScreenPixelSize.Width / 2f - truePixelWidth / 2f, this.ScreenPixelSize.Height / 2f - truePixelHeight / 2f)); break; default: throw new SeeingSharpGraphicsException($"Unable to handle transform mode {transformSettings.TransformMode}"); } // Apply current transform this.ApplyTransformStack(); }
/// <summary> /// Determine the distance from the mouse position to the screen space rectangle specified by the 4 points. /// </summary> static public float DistanceToRectangle(Vector2[] screenPoints, Vector2 mousePos) { bool oddNodes = false; int j = 4; for (int i = 0; i < 5; i++) { Vector3 v0 = screenPoints[EngineMath.RepeatIndex(i, 4)]; Vector3 v1 = screenPoints[EngineMath.RepeatIndex(j, 4)]; if ((v0.y > mousePos.y) != (v1.y > mousePos.y)) { if (mousePos.x < (v1.x - v0.x) * (mousePos.y - v0.y) / (v1.y - v0.y) + v0.x) { oddNodes = !oddNodes; } } j = i; } if (!oddNodes) { float dist, closestDist = -1f; for (int i = 0; i < 4; i++) { Vector3 v0 = screenPoints[i]; Vector3 v1 = screenPoints[EngineMath.RepeatIndex(i + 1, 4)]; dist = DistancePointToLineSegment(mousePos, v0, v1); if (dist < closestDist || closestDist < 0f) { closestDist = dist; } } return(closestDist); } else { return(0f); } }
public static void EnsureNotEqual( this Vector4 vectorValueLeft, Vector4 vectorValueRight, string checkedVariableName, string comparedVariableName, [CallerMemberName] string callerMethod = "") { if (string.IsNullOrEmpty(callerMethod)) { callerMethod = "Unknown"; } if (EngineMath.EqualsWithTolerance(vectorValueLeft.X, vectorValueRight.X) && EngineMath.EqualsWithTolerance(vectorValueLeft.Y, vectorValueRight.Y) && EngineMath.EqualsWithTolerance(vectorValueLeft.Z, vectorValueRight.Z) && EngineMath.EqualsWithTolerance(vectorValueLeft.W, vectorValueRight.W)) { throw new SeeingSharpCheckException(string.Format( "Vector {0} within method {1} with value {2} musst not be equal with the vector {3}!", checkedVariableName, callerMethod, vectorValueLeft, comparedVariableName)); } }
public static Modell ReadModell(string path) { if (!File.Exists(path)) { throw new Exception("File was not exist"); } string[] lines = File.ReadAllLines(path); List <Vector3> localVertices = new List <Vector3>(); List <Vector2> uv = new List <Vector2>(); List <int> uvIndex = new List <int>(); List <int> faces = new List <int>(); List <Vector3> normal = new List <Vector3>(); List <int> normalIndexes = new List <int>(); foreach (string line in lines) { if (line.Length > 0) { if (line[0] == 'v' && line[1] != 'n' && line[1] != 't') { int end = 0; bool finished = false; foreach (char chr in line) { if (chr == 'v' && !finished) { end++; } else if (chr == ' ' && !finished) { end++; } else { finished = true; } } string[] data = line.Substring(end, line.Length - end).Split(' '); localVertices.Add(new Vector3(float.Parse(data[0].Replace('.', ',')), float.Parse(data[1].Replace('.', ',')), float.Parse(data[2].Replace('.', ',')))); } else if (line[0] == 'f') { string[] data = line.Substring(2, line.Length - 2).Split(' '); foreach (string vert in data) { string[] v_index = vert.Split('/'); faces.Add(int.Parse(v_index[0])); uvIndex.Add(int.Parse(v_index[1])); normalIndexes.Add(int.Parse(v_index[2])); } } else if (line[0] == 'v' && line[1] == 't') { int end = 0; bool finished = false; foreach (char chr in line) { if (chr == 'v' && !finished) { end++; } else if (chr == 't' && !finished) { end++; } else if (chr == ' ' && !finished) { end++; } else { finished = true; } } string[] data = line.Substring(end, line.Length - end).Split(' '); uv.Add(new Vector2(float.Parse(data[0].Replace('.', ',')), float.Parse(data[1].Replace('.', ',')))); } else if (line[0] == 'v' && line[1] == 'n') { int end = 0; bool finished = false; foreach (char chr in line) { if (chr == 'v' && !finished) { end++; } else if (chr == ' ' && !finished) { end++; } else if (chr == 'n' && !finished) { end++; } else { finished = true; } } string[] data = line.Substring(end, line.Length - end).Split(' '); normal.Add(new Vector3(float.Parse(data[0].Replace('.', ',')), float.Parse(data[1].Replace('.', ',')), float.Parse(data[2].Replace('.', ',')))); } } } List <Vector3> finalVertices = new List <Vector3>(); List <Vector3> finalNormals = new List <Vector3>(); List <Vector2> finalUV = new List <Vector2>(); List <Texture2D> textures = new List <Texture2D>(); List <Color> colors = new List <Color>(); Random rnd = new Random(); Texture2D texture = LoadResources.ReadTexture(Directory.GetCurrentDirectory() + @"\Mods\Default\Textures\rock.jpg"); foreach (int vert_index in faces) { finalVertices.Add(localVertices[vert_index - 1]); textures.Add(texture); colors.Add(Color.FromArgb(255, rnd.Next(0, 255), rnd.Next(0, 255), rnd.Next(0, 255))); } foreach (int uv_index in uvIndex) { finalUV.Add(EngineMath.RotateVector(uv[uv_index - 1], 180)); } foreach (int normal_index in normalIndexes) { finalNormals.Add(normal[normal_index - 1]); } Modell modell = new Modell() { vertices = finalVertices.ToArray(), uv = finalUV.ToArray(), normal = finalNormals.ToArray(), location = path }; return(modell); }
static public float ParseAlpha(string text, int index) { int a = (EngineMath.HexToDecimal(text[index + 1]) << 4) | EngineMath.HexToDecimal(text[index + 2]); return(Mathf.Clamp01(a / 255f)); }
/// <summary> /// Sets the current geometry of this object. /// </summary> /// <param name="geometry">The new geometry to be set.</param> /// <param name="flatteningTolerance">The maximum bounds on the distance between points in the polygonal approximation of the geometry. Smaller values produce more accurate results but cause slower execution.</param> /// <param name="extrudeOptions">Additional options for extruding.</param> internal void SetGeometry( D2D.ID2D1Geometry geometry, float flatteningTolerance, ExtrudeGeometryOptions extrudeOptions = ExtrudeGeometryOptions.None) { // Get triangles out of given geometry List <D2D.Triangle[]>?generatedTriangles = null; using (var tessellationSink = new ExtruderTessellationSink()) { geometry.Tessellate(flatteningTolerance, tessellationSink); generatedTriangles = tessellationSink.Triangles; } // Ensure that triangle list is created if (_generatedTriangles == null) { _generatedTriangles = new List <D2D.Triangle[]>(); } // Define methods for calculating bounds var minX = float.MaxValue; var maxX = float.MinValue; var minY = float.MaxValue; var maxY = float.MinValue; var minPoint = Vector2.Zero; void UpdateMinWidthHeight(PointF actCorner) { if (actCorner.X < minX) { minX = actCorner.X; } if (actCorner.X > maxX) { maxX = actCorner.X; } if (actCorner.Y < minY) { minY = actCorner.Y; } if (actCorner.Y > maxY) { maxY = actCorner.Y; } } // Do some postprocessing var triangleCount = 0; var bounds = new SizeF(); foreach (var actTriangleArray in generatedTriangles) { foreach (var actTriangle in actTriangleArray) { UpdateMinWidthHeight(actTriangle.Point1); UpdateMinWidthHeight(actTriangle.Point2); UpdateMinWidthHeight(actTriangle.Point3); triangleCount++; } } if (triangleCount > 0) { bounds = new SizeF(maxX - minX, maxY - minY); minPoint = new Vector2(minX, minY); } // Change with / height of the geometry depending on ExtrudeGeometryOptions if (extrudeOptions.HasFlag(ExtrudeGeometryOptions.RescaleToUnitSize)) { var scaleFactorX = !EngineMath.EqualsWithTolerance(bounds.Width, 0f) ? 1f / bounds.Width : 1f; var scaleFactorY = !EngineMath.EqualsWithTolerance(bounds.Height, 0f) ? 1f / bounds.Height : 1f; if (scaleFactorX < scaleFactorY) { scaleFactorY = scaleFactorX; } else { scaleFactorX = scaleFactorY; } foreach (var actTriangleArray in generatedTriangles) { for (var loop = 0; loop < actTriangleArray.Length; loop++) { var actTriangle = actTriangleArray[loop]; actTriangle.Point1 = new PointF(actTriangle.Point1.X * scaleFactorX, actTriangle.Point1.Y * scaleFactorY); actTriangle.Point2 = new PointF(actTriangle.Point2.X * scaleFactorX, actTriangle.Point2.Y * scaleFactorY); actTriangle.Point3 = new PointF(actTriangle.Point3.X * scaleFactorX, actTriangle.Point3.Y * scaleFactorY); actTriangleArray[loop] = actTriangle; } } bounds = new SizeF( bounds.Width * scaleFactorX, bounds.Height * scaleFactorY); minPoint = new Vector2(minPoint.X * scaleFactorX, minPoint.Y * scaleFactorY); } // Change the origin depending on ExtrudeGeometryOptions if (extrudeOptions.HasFlag(ExtrudeGeometryOptions.ChangeOriginToCenter)) { var newOrigin = new Vector2( minPoint.X + bounds.Width / 2f, minPoint.Y + bounds.Height / 2f); foreach (var actTriangleArray in generatedTriangles) { for (var loop = 0; loop < actTriangleArray.Length; loop++) { var actTriangle = actTriangleArray[loop]; actTriangle.Point1 = MathConverter.RawFromVector2(MathConverter.Vector2FromRaw(actTriangle.Point1) - newOrigin); actTriangle.Point2 = MathConverter.RawFromVector2(MathConverter.Vector2FromRaw(actTriangle.Point2) - newOrigin); actTriangle.Point3 = MathConverter.RawFromVector2(MathConverter.Vector2FromRaw(actTriangle.Point3) - newOrigin); actTriangleArray[loop] = actTriangle; } } minPoint = new Vector2(0f, 0f); } // Apply values this.TriangleCount = triangleCount; this.Bounds = bounds; _generatedTriangles = generatedTriangles; }
/// <summary> /// Querries all current input states. /// </summary> public IEnumerable <InputStateBase> GetInputStates() { // Update connected states first for (int loop = 0; loop < m_controllers.Length; loop++) { bool isConnected = m_controllers[loop].IsConnected; if (!isConnected) { m_states[loop].NotifyConnected(false); continue; } m_states[loop].NotifyConnected(true); // Query all state structures XI.State xiState = m_controllers[loop].GetState(); XI.Gamepad xiGamepad = xiState.Gamepad; // Convert float values GamepadReportedState repState = new GamepadReportedState() { LeftThumbstickX = EngineMath.Clamp((float)xiGamepad.LeftThumbX / (float)short.MaxValue, -1f, 1f), LeftThumbstickY = EngineMath.Clamp((float)xiGamepad.LeftThumbY / (float)short.MaxValue, -1f, 1f), LeftTrigger = EngineMath.Clamp((float)xiGamepad.LeftTrigger / 255f, 0f, 1f), RightThumbstickX = EngineMath.Clamp((float)xiGamepad.RightThumbX / (float)short.MaxValue, -1f, 1f), RightThumbstickY = EngineMath.Clamp((float)xiGamepad.RightThumbY / (float)short.MaxValue, -1f, 1f), RightTrigger = EngineMath.Clamp((float)xiGamepad.RightTrigger / 255f, 0, 1f) }; // Convert button states GamepadButton pressedButtons = GamepadButton.None; if (xiGamepad.Buttons.HasFlag(XI.GamepadButtonFlags.A)) { pressedButtons |= GamepadButton.A; } if (xiGamepad.Buttons.HasFlag(XI.GamepadButtonFlags.B)) { pressedButtons |= GamepadButton.B; } if (xiGamepad.Buttons.HasFlag(XI.GamepadButtonFlags.Back)) { pressedButtons |= GamepadButton.View; } if (xiGamepad.Buttons.HasFlag(XI.GamepadButtonFlags.DPadDown)) { pressedButtons |= GamepadButton.DPadDown; } if (xiGamepad.Buttons.HasFlag(XI.GamepadButtonFlags.DPadLeft)) { pressedButtons |= GamepadButton.DPadLeft; } if (xiGamepad.Buttons.HasFlag(XI.GamepadButtonFlags.DPadRight)) { pressedButtons |= GamepadButton.DPadRight; } if (xiGamepad.Buttons.HasFlag(XI.GamepadButtonFlags.DPadUp)) { pressedButtons |= GamepadButton.DPadUp; } if (xiGamepad.Buttons.HasFlag(XI.GamepadButtonFlags.LeftShoulder)) { pressedButtons |= GamepadButton.LeftShoulder; } if (xiGamepad.Buttons.HasFlag(XI.GamepadButtonFlags.LeftThumb)) { pressedButtons |= GamepadButton.LeftThumbstick; } if (xiGamepad.Buttons.HasFlag(XI.GamepadButtonFlags.RightShoulder)) { pressedButtons |= GamepadButton.RightShoulder; } if (xiGamepad.Buttons.HasFlag(XI.GamepadButtonFlags.RightThumb)) { pressedButtons |= GamepadButton.RightThumbstick; } if (xiGamepad.Buttons.HasFlag(XI.GamepadButtonFlags.Start)) { pressedButtons |= GamepadButton.Menu; } if (xiGamepad.Buttons.HasFlag(XI.GamepadButtonFlags.X)) { pressedButtons |= GamepadButton.X; } if (xiGamepad.Buttons.HasFlag(XI.GamepadButtonFlags.Y)) { pressedButtons |= GamepadButton.Y; } repState.Buttons = pressedButtons; // Report controller state to the system m_states[loop].NotifyState(repState); } // Now return all input states for (int loop = 0; loop < m_states.Length; loop++) { yield return(m_states[loop]); } }
/// <summary> /// Loads a ac file from the given uri /// </summary> internal static ACFileInfo LoadFile(Stream inStream) { ACFileInfo? result = null; StreamReader?reader = null; try { reader = new StreamReader(inStream); //Check for correct header var header = reader.ReadLine(); if (header == null || !header.StartsWith("AC3D")) { throw new SeeingSharpGraphicsException("Header of AC3D file not found!"); } //Create file information object result = new ACFileInfo(); //Create a loaded objects stack var loadedObjects = new Stack <ACObjectInfo>(); var parentObjects = new Stack <ACObjectInfo>(); ACSurface?currentSurface = null; //Read the file while (!reader.EndOfStream) { var actLine = reader.ReadLine() !.Trim(); var firstWord = string.Empty; var spaceIndex = actLine.IndexOf(' '); if (spaceIndex == -1) { firstWord = actLine; } else { firstWord = firstWord = actLine.Substring(0, spaceIndex); } switch (firstWord) { //New Material info case "MATERIAL": var materialInfo = new ACMaterialInfo(); { //Get the name of the material var materialData = actLine.Split(' '); if (materialData.Length > 1) { materialInfo.Name = materialData[1].Trim(' ', '"'); } //Parse components for (var loop = 0; loop < materialData.Length; loop++) { switch (materialData[loop]) { case "rgb": var diffuseColor = materialInfo.Diffuse; diffuseColor.Alpha = 1f; diffuseColor.Red = float.Parse(materialData[loop + 1], CultureInfo.InvariantCulture); diffuseColor.Green = float.Parse(materialData[loop + 2], CultureInfo.InvariantCulture); diffuseColor.Blue = float.Parse(materialData[loop + 3], CultureInfo.InvariantCulture); materialInfo.Diffuse = diffuseColor; break; case "amb": var ambientColor = new Color4(); ambientColor.Red = float.Parse(materialData[loop + 1], CultureInfo.InvariantCulture); ambientColor.Green = float.Parse(materialData[loop + 2], CultureInfo.InvariantCulture); ambientColor.Blue = float.Parse(materialData[loop + 3], CultureInfo.InvariantCulture); materialInfo.Ambient = ambientColor; break; case "emis": var emissiveColor = new Color4(); emissiveColor.Red = float.Parse(materialData[loop + 1], CultureInfo.InvariantCulture); emissiveColor.Green = float.Parse(materialData[loop + 2], CultureInfo.InvariantCulture); emissiveColor.Blue = float.Parse(materialData[loop + 3], CultureInfo.InvariantCulture); materialInfo.Emissive = emissiveColor; break; case "spec": var specularColor = new Color4(); specularColor.Red = float.Parse(materialData[loop + 1], CultureInfo.InvariantCulture); specularColor.Green = float.Parse(materialData[loop + 2], CultureInfo.InvariantCulture); specularColor.Blue = float.Parse(materialData[loop + 3], CultureInfo.InvariantCulture); materialInfo.Specular = specularColor; break; case "shi": materialInfo.Shininess = float.Parse(materialData[loop + 1], CultureInfo.InvariantCulture); break; case "trans": diffuseColor = materialInfo.Diffuse; diffuseColor.Alpha = 1f - EngineMath.Clamp(float.Parse(materialData[loop + 1], CultureInfo.InvariantCulture), 0f, 1f); materialInfo.Diffuse = diffuseColor; break; } } result.Materials.Add(materialInfo); } break; //New object starts here case "OBJECT": { var newObject = new ACObjectInfo(); var lineData = actLine.Split(' '); if (lineData[1] == "poly") { newObject.Type = ACObjectType.Poly; } else if (lineData[1] == "group") { newObject.Type = ACObjectType.Group; } else if (lineData[1] == "world") { newObject.Type = ACObjectType.World; } loadedObjects.Push(newObject); } break; //End of an object, kids following case "kids": if (loadedObjects.Count == 0) { break; } { //Parse kid count var kidCount = 0; var lineData = actLine.Split(' '); if (lineData.Length >= 1) { int.TryParse(lineData[1], out kidCount); } var currentObject = loadedObjects.Peek(); if (currentObject != null) { //AddObject object to parent object, if any related var addedToParent = false; if (parentObjects.Count > 0) { var currentParent = parentObjects.Peek(); if (currentParent.Children.Count < currentParent.KidCount) { currentParent.Children.Add(currentObject); addedToParent = true; } else { while (parentObjects.Count > 0) { parentObjects.Pop(); if (parentObjects.Count == 0) { break; } currentParent = parentObjects.Peek(); if (currentParent == null) { break; } if (currentParent.Children.Count < currentParent.KidCount) { break; } } if (currentParent != null && currentParent.Children.Count < currentParent.KidCount) { currentParent.Children.Add(currentObject); addedToParent = true; } } } //Enable this object as parent object currentObject.KidCount = kidCount; if (currentObject.KidCount > 0) { parentObjects.Push(currentObject); } //AddObject to scene root if this object has no parent loadedObjects.Pop(); if (!addedToParent) { if (loadedObjects.Count == 0) { result.Objects.Add(currentObject); } else { loadedObjects.Peek().Children.Add(currentObject); } } currentObject = null; } } break; //Current object's name case "name": if (loadedObjects.Count == 0) { break; } { var currentObject = loadedObjects.Peek(); if (currentObject != null) { currentObject.Name = actLine.Replace("name ", "").Replace("\"", ""); } } break; case "data": break; case "texture": if (loadedObjects.Count == 0) { break; } { var currentObject = loadedObjects.Peek(); if (currentObject != null) { var lineData = actLine.Split(' '); currentObject.Texture = lineData[1].Trim('"'); } } break; case "texrep": if (loadedObjects.Count == 0) { break; } { var currentObject = loadedObjects.Peek(); if (currentObject != null) { var lineData = actLine.Split(' '); var repetition = new Vector2 { X = float.Parse(lineData[1], CultureInfo.InvariantCulture), Y = float.Parse(lineData[2], CultureInfo.InvariantCulture) }; currentObject.TextureRepeat = repetition; } } break; case "texoff": if (loadedObjects.Count == 0) { break; } { var currentObject = loadedObjects.Peek(); if (currentObject != null) { var lineData = actLine.Split(' '); var offset = new Vector2 { X = float.Parse(lineData[1], CultureInfo.InvariantCulture), Y = float.Parse(lineData[2], CultureInfo.InvariantCulture) }; currentObject.TextureRepeat = offset; } } break; case "rot": if (loadedObjects.Count == 0) { break; } { var currentObject = loadedObjects.Peek(); if (currentObject != null) { var lineData = actLine.Split(' '); var rotation = Matrix4x4.Identity; rotation.M11 = !string.IsNullOrEmpty(lineData[1]) ? float.Parse(lineData[1], CultureInfo.InvariantCulture) : 0f; rotation.M12 = !string.IsNullOrEmpty(lineData[2]) ? float.Parse(lineData[2], CultureInfo.InvariantCulture) : 0f; rotation.M13 = !string.IsNullOrEmpty(lineData[3]) ? float.Parse(lineData[3], CultureInfo.InvariantCulture) : 0f; rotation.M21 = !string.IsNullOrEmpty(lineData[4]) ? float.Parse(lineData[4], CultureInfo.InvariantCulture) : 0f; rotation.M22 = !string.IsNullOrEmpty(lineData[5]) ? float.Parse(lineData[5], CultureInfo.InvariantCulture) : 0f; rotation.M23 = !string.IsNullOrEmpty(lineData[6]) ? float.Parse(lineData[6], CultureInfo.InvariantCulture) : 0f; rotation.M31 = !string.IsNullOrEmpty(lineData[7]) ? float.Parse(lineData[7], CultureInfo.InvariantCulture) : 0f; rotation.M32 = !string.IsNullOrEmpty(lineData[8]) ? float.Parse(lineData[8], CultureInfo.InvariantCulture) : 0f; rotation.M33 = !string.IsNullOrEmpty(lineData[9]) ? float.Parse(lineData[9], CultureInfo.InvariantCulture) : 0f; currentObject.Rotation = rotation; } } break; case "url": if (loadedObjects.Count == 0) { break; } { var currentObject = loadedObjects.Peek(); if (currentObject != null) { var lineData = actLine.Split(' '); currentObject.Url = lineData[1].Trim('"'); } } break; //Current object's location case "loc": if (loadedObjects.Count == 0) { break; } { var currentObject = loadedObjects.Peek(); if (currentObject != null) { var lineData = actLine.Split(' '); var location = new Vector3 { X = float.Parse(lineData[1], CultureInfo.InvariantCulture), Y = float.Parse(lineData[2], CultureInfo.InvariantCulture), Z = float.Parse(lineData[3], CultureInfo.InvariantCulture) }; currentObject.Translation = location; } } break; case "numvert": if (loadedObjects.Count == 0) { break; } { var currentObject = loadedObjects.Peek(); if (currentObject != null) { var lineData = actLine.Split(' '); var numberOfVertices = int.Parse(lineData[1], CultureInfo.InvariantCulture); for (var loop = 0; loop < numberOfVertices; loop++) { var actInnerLine = reader.ReadLine() !.Trim(); var splittedVertex = actInnerLine.Split(' '); var position = new Vector3 { X = float.Parse(splittedVertex[0], CultureInfo.InvariantCulture), Y = float.Parse(splittedVertex[1], CultureInfo.InvariantCulture), Z = float.Parse(splittedVertex[2], CultureInfo.InvariantCulture) }; currentObject.Vertices.Add(new ACVertex { Position = position }); } } } break; //Start of a list of surfaces case "numsurf": break; //New surface starts here case "SURF": { if (currentSurface == null) { currentSurface = new ACSurface(); } var lineData = actLine.Split(' '); lineData[1] = lineData[1].Substring(2); currentSurface.Flags = int.Parse(lineData[1], NumberStyles.HexNumber); } break; //Current surface's material case "mat": { if (currentSurface == null) { currentSurface = new ACSurface(); } var lineData = actLine.Split(' '); currentSurface.Material = int.Parse(lineData[1], CultureInfo.InvariantCulture); } break; //Current surface's indices case "refs": if (loadedObjects.Count == 0) { break; } { if (currentSurface == null) { currentSurface = new ACSurface(); } var lineData = actLine.Split(' '); var numberOfRefs = int.Parse(lineData[1], CultureInfo.InvariantCulture); for (var loop = 0; loop < numberOfRefs; loop++) { var actInnerLine = reader.ReadLine() !.Trim(); var splittedRef = actInnerLine.Split(' '); var texCoord = new Vector2(); int vertexReference = ushort.Parse(splittedRef[0], CultureInfo.InvariantCulture); texCoord.X = float.Parse(splittedRef[1], CultureInfo.InvariantCulture); texCoord.Y = float.Parse(splittedRef[2], CultureInfo.InvariantCulture); currentSurface.TextureCoordinates.Add(texCoord); currentSurface.VertexReferences.Add(vertexReference); } var currentObject = loadedObjects.Peek(); currentObject?.Surfaces.Add(currentSurface); currentSurface = null; } break; } } } finally { SeeingSharpUtil.SafeDispose(ref reader); } return(result); }
/// <summary> /// Creates and adds the root for all imported scene objects. /// </summary> public void FinishLoading(BoundingBox boundingBox) { this.EnsureNotFinished(); try { // Generic checks if (this.Objects.Count == 0) { throw new SeeingSharpException("No objects imported"); } if (EngineMath.EqualsWithTolerance(boundingBox.Width, 0) || EngineMath.EqualsWithTolerance(boundingBox.Height, 0) || EngineMath.EqualsWithTolerance(boundingBox.Depth, 0)) { throw new SeeingSharpException($"BoundingBox of the loaded model data seems to be empty (Width={boundingBox.Width}, Height={boundingBox.Height}, Depth={boundingBox.Height}"); } // Create root for the imported object graph var rootObject = new ScenePivotObject(); rootObject.TransformationType = SpacialTransformationType.ScalingTranslationEulerAngles; rootObject.Name = $"{IMPORT_ROOT_NODE_NAME_PREFIX} {_importId}"; // Configure base transformation of the root object switch (_importOptions.ResourceCoordinateSystem) { case CoordinateSystem.LeftHanded_UpY: break; case CoordinateSystem.LeftHanded_UpZ: rootObject.Scaling = new Vector3(1f, -1f, 1f); rootObject.RotationEuler = new Vector3(-EngineMath.RAD_90DEG, 0f, 0f); break; case CoordinateSystem.RightHanded_UpY: rootObject.Scaling = new Vector3(1f, 1f, -1f); break; case CoordinateSystem.RightHanded_UpZ: rootObject.Scaling = new Vector3(-1f, 1f, -1f); rootObject.RotationEuler = new Vector3(EngineMath.RAD_90DEG, 0f, 0f); break; } // Configure position and scaling of the root object if (_importOptions.FitToCube) { var scaleFactor = Math.Min( 1f / boundingBox.Width, Math.Min(1f / boundingBox.Height, 1f / boundingBox.Depth)); rootObject.Scaling *= scaleFactor; rootObject.Position = new Vector3( (0f - (boundingBox.Minimum.X + (boundingBox.Maximum.X - boundingBox.Minimum.X) / 2f)) * scaleFactor, (0f - (boundingBox.Minimum.Y + (boundingBox.Maximum.Y - boundingBox.Minimum.Y) / 2f)) * scaleFactor, (0f - (boundingBox.Minimum.Z + (boundingBox.Maximum.Z - boundingBox.Minimum.Z) / 2f)) * scaleFactor); } // Find current root objects and assign them as child to the new root object foreach (var actRootObject in this.FindRootObjects()) { _parentChildRelationships.Add( new ParentChildRelationship(rootObject, actRootObject)); } // AddObject the object finally _objects.Add(rootObject); this.RootObject = rootObject; this.BoundingBox = boundingBox; _isValid = true; } catch (Exception ex) { this.FinishLoading(ex); } finally { _isFinished = true; } }
/// <summary> /// Queries for the ObjectId at the given location. /// </summary> /// <param name="texture">The uploaded texture.</param> /// <param name="xPos">The x position where to start.</param> /// <param name="yPos">The y position where to start.</param> public static unsafe float QueryForObjectId(this MemoryMappedTexture <float> texture, int xPos, int yPos) { var pixelSize = texture.PixelSize; if (xPos < 0) { throw new ArgumentException("xPos"); } if (xPos >= pixelSize.Width) { throw new ArgumentException("xPos"); } if (yPos < 0) { throw new ArgumentException("yPos"); } if (yPos >= pixelSize.Height) { throw new ArgumentException("yPos"); } // Loop over more pixels to be sure, that we are directly facing one object // => This is needed because of manipulations done by multisampling (=Antialiasing) var pointerNative = texture.GetNativePointer(); var currentX = xPos; var currentY = yPos; var lastObjId = pointerNative[currentY * pixelSize.Width + currentX]; for (var loopActQueryStep = 0; loopActQueryStep < s_queryObjectIdSteps.Length; loopActQueryStep++) { // Calculate current query location var currentStep = s_queryObjectIdSteps[loopActQueryStep]; currentX += currentStep.X; currentY += currentStep.Y; // Check whether we are still in a valid pixel coordinate if (currentX < 0) { continue; } if (currentX >= pixelSize.Width) { continue; } if (currentY < 0) { continue; } if (currentY >= pixelSize.Height) { continue; } // Read current value and compare with last one // (If equal, than at least two pixels are the same => Return this ObjectId) var currObjId = pointerNative[currentY * pixelSize.Width + currentX]; if (EngineMath.EqualsWithTolerance(currObjId, lastObjId)) { return(currObjId); } // No match found, continue with next one lastObjId = currObjId; } // No clear match found return(0f); }