From 6aac31d3e502b272273b31576cae5328a7c1c208 Mon Sep 17 00:00:00 2001 From: Martin Date: Mon, 24 Jun 2024 14:18:31 +0200 Subject: [PATCH] Remove moved projects - Aardvark.Data.Photometry - Aardvark.Data.Wavefront Moved to: https://github.com/aardvark-platform/aardvark.data --- .../Aardvark.Algodat.Tests.csproj | 1 - src/Aardvark.Algodat.Tests/PhotometryTest.cs | 252 --------- src/Aardvark.Algodat.sln | 16 +- .../Aardvark.Data.Photometry.csproj | 16 - src/Aardvark.Data.Photometry/IESData.cs | 118 ----- src/Aardvark.Data.Photometry/IESParser.cs | 145 ----- .../IntensityProfileSampler.cs | 162 ------ src/Aardvark.Data.Photometry/LDTData.cs | 107 ---- src/Aardvark.Data.Photometry/LDTParser.cs | 146 ----- .../LightMeasurementData.cs | 499 ------------------ src/Aardvark.Data.Photometry/Photometry.cs | 58 -- .../PhotometryDataCalculations.cs | 385 -------------- src/Aardvark.Data.Photometry/TextParser.cs | 50 -- src/Aardvark.Data.Photometry/paket.references | 2 - src/Aardvark.Data.Photometry/paket.template | 11 - .../Aardvark.Data.Wavefront.csproj | 20 - src/Aardvark.Data.Wavefront/Exporter.cs | 465 ---------------- src/Aardvark.Data.Wavefront/LICENSE | 203 ------- src/Aardvark.Data.Wavefront/MtlParser.cs | 119 ----- src/Aardvark.Data.Wavefront/ObjParser.cs | 494 ----------------- src/Aardvark.Data.Wavefront/Primitives.cs | 115 ---- .../WavefrontMaterial.cs | 43 -- .../WavefrontObject.cs | 226 -------- .../WavefrontParser.cs | 74 --- src/Aardvark.Data.Wavefront/paket.references | 1 - src/Aardvark.Data.Wavefront/paket.template | 11 - 26 files changed, 2 insertions(+), 3737 deletions(-) delete mode 100644 src/Aardvark.Algodat.Tests/PhotometryTest.cs delete mode 100644 src/Aardvark.Data.Photometry/Aardvark.Data.Photometry.csproj delete mode 100644 src/Aardvark.Data.Photometry/IESData.cs delete mode 100644 src/Aardvark.Data.Photometry/IESParser.cs delete mode 100644 src/Aardvark.Data.Photometry/IntensityProfileSampler.cs delete mode 100644 src/Aardvark.Data.Photometry/LDTData.cs delete mode 100644 src/Aardvark.Data.Photometry/LDTParser.cs delete mode 100644 src/Aardvark.Data.Photometry/LightMeasurementData.cs delete mode 100644 src/Aardvark.Data.Photometry/Photometry.cs delete mode 100644 src/Aardvark.Data.Photometry/PhotometryDataCalculations.cs delete mode 100644 src/Aardvark.Data.Photometry/TextParser.cs delete mode 100644 src/Aardvark.Data.Photometry/paket.references delete mode 100644 src/Aardvark.Data.Photometry/paket.template delete mode 100644 src/Aardvark.Data.Wavefront/Aardvark.Data.Wavefront.csproj delete mode 100644 src/Aardvark.Data.Wavefront/Exporter.cs delete mode 100644 src/Aardvark.Data.Wavefront/LICENSE delete mode 100644 src/Aardvark.Data.Wavefront/MtlParser.cs delete mode 100644 src/Aardvark.Data.Wavefront/ObjParser.cs delete mode 100644 src/Aardvark.Data.Wavefront/Primitives.cs delete mode 100644 src/Aardvark.Data.Wavefront/WavefrontMaterial.cs delete mode 100644 src/Aardvark.Data.Wavefront/WavefrontObject.cs delete mode 100644 src/Aardvark.Data.Wavefront/WavefrontParser.cs delete mode 100644 src/Aardvark.Data.Wavefront/paket.references delete mode 100644 src/Aardvark.Data.Wavefront/paket.template diff --git a/src/Aardvark.Algodat.Tests/Aardvark.Algodat.Tests.csproj b/src/Aardvark.Algodat.Tests/Aardvark.Algodat.Tests.csproj index 0690ff15..c5607764 100644 --- a/src/Aardvark.Algodat.Tests/Aardvark.Algodat.Tests.csproj +++ b/src/Aardvark.Algodat.Tests/Aardvark.Algodat.Tests.csproj @@ -19,7 +19,6 @@ - diff --git a/src/Aardvark.Algodat.Tests/PhotometryTest.cs b/src/Aardvark.Algodat.Tests/PhotometryTest.cs deleted file mode 100644 index 6b958f79..00000000 --- a/src/Aardvark.Algodat.Tests/PhotometryTest.cs +++ /dev/null @@ -1,252 +0,0 @@ -using Aardvark.Base; -using Aardvark.Data.Photometry; -using NUnit.Framework; -using System.IO; -using System.Linq; - -namespace Aardvark.Data.Photometry -{ - [TestFixture] - public class PhotometryTest - { - static readonly string PhotometryDataPath = @"C:\Users\luksch\Desktop\Photometry Test Files"; - - [Test] - public void GetCPlaneTest() - { - var ldtC1 = new LDTData() - { - LampSets = new LDTLampData() { TotalFlux = 1000, Number = 1 }.IntoArray(), - HorizontalAngles = new double[] { 0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330 }, - VerticleAngles = new double[] {0, 45, 90, 135, 180 }, - VertAngleStep = 45, - LightOutputRatioLuminaire = 100, - Symmetry = LDTSymmetry.C1, - Data = new Matrix(5, 7).SetByCoord((x, y) => y), - }; - - var rows = new double[] { 3, 4, 5, 6, 5, 4, 3, 2, 1, 0, 1, 2 }; - - EvaluatePlanes(ldtC1, rows); - - var ldtQuarter = new LDTData() - { - LampSets = new LDTLampData() { TotalFlux = 1000, Number = 1 }.IntoArray(), - HorizontalAngles = new double[] { 0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330 }, - VerticleAngles = new double[] { 0, 45, 90, 135, 180 }, - VertAngleStep = 45, - LightOutputRatioLuminaire = 100, - Symmetry = LDTSymmetry.Quarter, - Data = new Matrix(5, 4).SetByCoord((x, y) => y), - }; - - var rowsQuarter = new double[] { 0, 1, 2, 3, 2, 1, 0, 1, 2, 3, 2, 1 }; - - EvaluatePlanes(ldtQuarter, rowsQuarter); - } - - static void EvaluatePlanes(LDTData ldt, double[] rows) - { - var data = new LightMeasurementData(ldt); - - for (int i = 0; i < rows.Length; i++) - { - var angle = ldt.HorizontalAngles[i]; - var p = data.GetCPlane(angle); - var row = p.First().Item2; - var rowRef = rows[i]; - var correct = row == rowRef; - Assert.IsTrue(correct); - } - } - - [Test, Ignore("Requires Data Files")] - public void ZonesTest() - { - //{ - // var file = @"C:\Users\Lui\Downloads\60715074_(STD).ldt"; - // var zones = new[] { 249.1, 351.3, 130.2, 13.4, 3.4, 1.8, 0.6, 0, 0, - // 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - // EvaluateZones(file, zones); - //} - - //{ - // var file = @"C:\Users\Lui\Downloads\60714706_(STD).ldt"; - // var zones = new[] { 114.9, 297.0, 358.8, 303.4, 186.6, 94.5, 32.0, 5.2, 0.3, - // 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - // EvaluateZones(file, zones); - //} - - foreach (var f in Directory.GetFiles(PhotometryDataPath, "*.ldt")) - { - EvaluateZonesSampling(f); - } - } - - static void EvaluateZones(string file, double[] refZones) - { - var data = LightMeasurementData.FromFile(file); - var zones = data.CalculateZones(); - var sampler = new IntensityProfileSampler(data); - var zonesSampled = sampler.SampleZones(16000); - - Assert.True(zones.Length == 18); - - var totFluxRef = data.LumFlux; - var totFlux = zones.Sum(); - var totFluxSampled = zonesSampled.Sum(); - - var fluxRatio = totFlux / totFluxRef; - var fluxRatioSampled = totFluxSampled / totFluxRef; - - Assert.True(fluxRatio.ApproximateEquals(1, 1e-2)); - Assert.True(fluxRatioSampled.ApproximateEquals(1, 1e-2)); - - var e = data.LumFlux * 1e-2; - - for (int i = 0; i < 18; i++) - { - Assert.True(zones[i].ApproximateEquals(refZones[i], e)); - Assert.True(zonesSampled[i].ApproximateEquals(refZones[i], e)); - - var ratio = refZones[i] > 0 ? zones[i] / refZones[i] : zones[i] > 0 ? double.MaxValue : 1.0; - if (!ratio.ApproximateEquals(1.0, 0.05)) - Report.Warn("Zone {0} Difference", i); - - var ratio2 = refZones[i] > 0 ? zonesSampled[i] / refZones[i] : zonesSampled[i] > 0 ? double.MaxValue : 1.0; - if (!ratio2.ApproximateEquals(1.0, 0.05)) - Report.Warn("Zone {0} Difference Sampled", i); - } - } - - static void EvaluateZonesSampling(string file) - { - Report.Line("Evaluating Zones: {0}", Path.GetFileName(file)); - - var data = LightMeasurementData.FromFile(file); - - Report.Line("Info: Symmetry={0} VerticalRange={1}", data.HorizontalSymmetry, data.VerticalRange); - - var zones = data.CalculateZones(); - var sampler = new IntensityProfileSampler(data); - var zonesSampled = sampler.SampleZones(16000); - - Assert.True(zones.Length == 18); - - var totFlux = zones.Sum(); - var totFluxSampled = zonesSampled.Sum(); - - var fluxRatio = totFlux / totFluxSampled; - - Assert.True(fluxRatio.ApproximateEquals(1, 1e-2)); - - var e = data.LumFlux * 1e-2; - - var rmsError = 0.0; - - for (int i = 0; i < 18; i++) - { - var error = zonesSampled[i] > 0 ? 1 - zones[i] / zonesSampled[i] : zones[i] > 0 ? 1 : 0; - rmsError += error.Square(); - - Report.Line("Zone {0} Error={1:0.00}%", i, (error).Abs() * 100); - - Assert.True(zones[i].ApproximateEquals(zonesSampled[i], e)); - Assert.True(zonesSampled[i].ApproximateEquals(zonesSampled[i], e)); - - var ratio = zonesSampled[i] > 0 ? zones[i] / zonesSampled[i] : zones[i] > 0 ? double.MaxValue : 1.0; - if (!ratio.ApproximateEquals(1.0, 0.05)) - Report.Warn("Zone {0} Difference", i); - } - - Report.Line("RMS Error={0:0.00000}", (rmsError / 18).Sqrt()); - } - - [Test, Ignore("Requires Data Files")] - public void LumFluxTest() - { - foreach (var f in Directory.GetFiles(PhotometryDataPath, "*.ldt")) - { - EvaluateLumFlux(f); - Report.Line(""); - } - } - - static void EvaluateLumFlux(string file) - { - Report.Line("Evaluating Lum Flux: {0}", Path.GetFileName(file)); - - var data = LightMeasurementData.FromFile(file); - - Report.Line("Info: Symmetry={0} VerticalRange={1}", data.HorizontalSymmetry, data.VerticalRange); - - var eqMtx = data.BuildEquidistantMatrix(); - var lumFluxCalc = data.CalculateLumFlux(); - var lumFluxCalcEq = LightMeasurementData.CalculateLumFlux(eqMtx, data.VerticalRange); - var sampler = new IntensityProfileSampler(data); - var lumFluxSample = sampler.SampleLumFlux(16000); - - var ratioCalc = lumFluxCalc / data.LumFlux; - var ratioCalcEq = lumFluxCalcEq / data.LumFlux; - var ratioSample = lumFluxSample / data.LumFlux; - - var errorCalc = (1 - ratioCalc).Abs(); - var errorCalcEq = (1 - ratioCalcEq).Abs(); - var errorSample = (1 - ratioSample).Abs(); - - Report.Line("Specified LumFlux: " + data.LumFlux); - Report.Line("Calculated LumFlux (Sampling/Reference): " + lumFluxSample); // assuming sampling is unbiased and data transformation works as intented - Report.Line("Calculated LumFlux (Segments): " + lumFluxCalc); - Report.Line("Calculated LumFlux (EqDistPoints): " + lumFluxCalcEq); - - var better = errorCalc < errorCalcEq ? "Calc" : "CalcEq"; - Report.Line("{0} Calculation More Accurate [Calc Error={1:0.00}%, CalcEq Error={2:0.00}% Sample={3:0.00}%", better, errorCalc * 100, errorCalcEq * 100, errorSample * 100); - - Assert.True(ratioCalc.ApproximateEquals(1, 0.05), "Luminous flux calculation broken or photometry file contains invalid data"); - Assert.True(ratioCalcEq.ApproximateEquals(1, 0.12), "Luminous flux calculation broken or photometry file contains invalid data"); - Assert.True(ratioSample.ApproximateEquals(1, 0.05), "Luminous flux calculation broken or photometry file contains invalid data"); - } - - public static void TestDirection(double gamma, double c, V3d dir) - { - var (c2, g2) = Photometry.CartesianToSpherical(dir); - if (!c2.ApproximateEquals(c, 1e-7) || !g2.ApproximateEquals(gamma, 1e-7)) - Report.Line("FAIL"); - var v = Photometry.SphericalToCartesian(c, gamma); - if (!v.ApproximateEquals(dir, 1e-7)) - Report.Line("FAIL"); - } - - [Test] - public static void CoordinateSystem() - { - // gamma 0° / -Z-Axis - TestDirection(0, Constant.Pi, -V3d.ZAxis); // c angle is undefined, but outcome will be 180° - // gamma 180° / Z-Axis - TestDirection(Constant.Pi, 0, V3d.ZAxis); // c angle is undefined, but outcome will be 0° - - // gamma 90° + C=0° / X-Axis - TestDirection(Constant.PiHalf, 0, V3d.XAxis); - // gamma 90° + C=90° / Y-Axis - TestDirection(Constant.PiHalf, Constant.PiHalf, V3d.YAxis); - // gamma 90° + C=180° / -X-Axis - TestDirection(Constant.PiHalf, Constant.Pi, -V3d.XAxis); - // gamma 90° + C=270° / -Y-Axis - TestDirection(Constant.PiHalf, Constant.Pi * 3 / 2, -V3d.YAxis); - - var rnd = new RandomSystem(2143); - for (int i = 0; i < 1000; i++) - { - var v = RandomSample.Spherical(rnd.UniformDouble(), rnd.UniformDouble()); - - var (c, gamma) = Photometry.CartesianToSpherical(v); - var v2 = Photometry.SphericalToCartesian(c, gamma); - - if (!v.ApproximateEquals(v2, 1e-3)) - Report.Line("FAIL"); - else - Report.Line("OK"); - } - } - } -} diff --git a/src/Aardvark.Algodat.sln b/src/Aardvark.Algodat.sln index f46776aa..3f4e79b7 100644 --- a/src/Aardvark.Algodat.sln +++ b/src/Aardvark.Algodat.sln @@ -36,8 +36,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aardvark.Geometry.Normals", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImportTest", "Apps\ImportTest\ImportTest.csproj", "{0595D792-52A4-4DE1-A39F-6A99D199471A}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aardvark.Data.Photometry", "Aardvark.Data.Photometry\Aardvark.Data.Photometry.csproj", "{9CCC776B-46E0-453F-BF24-BC85D0979067}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aardvark.Physics.Sky", "Aardvark.Physics.Sky\Aardvark.Physics.Sky.csproj", "{00D02F5B-5278-4867-9F55-777ACF03EB1E}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aardvark.Data.Points.LasZip", "Aardvark.Data.Points.LasZip\Aardvark.Data.Points.LasZip.csproj", "{997D436A-6A9F-4C2E-8D71-39410CC1EDF2}" @@ -73,13 +71,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ply.Net", "Ply.Net\Ply.Net. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aardvark.Data.Points.Ply", "Aardvark.Data.Points.Ply\Aardvark.Data.Points.Ply.csproj", "{7E5CEB6E-F437-47D9-905B-FDEEABC9D19D}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aardvark.Data.Wavefront", "Aardvark.Data.Wavefront\Aardvark.Data.Wavefront.csproj", "{7C25100A-8774-422C-90FB-FA113F798CB4}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unofficial.laszip.netstandard", "Unofficial.laszip.netstandard\Unofficial.laszip.netstandard.csproj", "{AC84C458-5A8A-4EC9-A1B3-15CC52DA2E91}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "import", "import\import.csproj", "{000B3CDA-C67B-4F6A-B6F8-69A1B5052343}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "ScratchFSharp", "Apps\ScratchFSharp\ScratchFSharp.fsproj", "{E5B3A633-A8F4-4D56-BB64-4A885E22B3B2}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "ScratchFSharp", "Apps\ScratchFSharp\ScratchFSharp.fsproj", "{E5B3A633-A8F4-4D56-BB64-4A885E22B3B2}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -151,10 +147,6 @@ Global {0595D792-52A4-4DE1-A39F-6A99D199471A}.Debug|Any CPU.Build.0 = Debug|Any CPU {0595D792-52A4-4DE1-A39F-6A99D199471A}.Release|Any CPU.ActiveCfg = Release|Any CPU {0595D792-52A4-4DE1-A39F-6A99D199471A}.Release|Any CPU.Build.0 = Release|Any CPU - {9CCC776B-46E0-453F-BF24-BC85D0979067}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9CCC776B-46E0-453F-BF24-BC85D0979067}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9CCC776B-46E0-453F-BF24-BC85D0979067}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9CCC776B-46E0-453F-BF24-BC85D0979067}.Release|Any CPU.Build.0 = Release|Any CPU {00D02F5B-5278-4867-9F55-777ACF03EB1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {00D02F5B-5278-4867-9F55-777ACF03EB1E}.Debug|Any CPU.Build.0 = Debug|Any CPU {00D02F5B-5278-4867-9F55-777ACF03EB1E}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -183,10 +175,6 @@ Global {7E5CEB6E-F437-47D9-905B-FDEEABC9D19D}.Debug|Any CPU.Build.0 = Debug|Any CPU {7E5CEB6E-F437-47D9-905B-FDEEABC9D19D}.Release|Any CPU.ActiveCfg = Release|Any CPU {7E5CEB6E-F437-47D9-905B-FDEEABC9D19D}.Release|Any CPU.Build.0 = Release|Any CPU - {7C25100A-8774-422C-90FB-FA113F798CB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7C25100A-8774-422C-90FB-FA113F798CB4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7C25100A-8774-422C-90FB-FA113F798CB4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7C25100A-8774-422C-90FB-FA113F798CB4}.Release|Any CPU.Build.0 = Release|Any CPU {AC84C458-5A8A-4EC9-A1B3-15CC52DA2E91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AC84C458-5A8A-4EC9-A1B3-15CC52DA2E91}.Debug|Any CPU.Build.0 = Debug|Any CPU {AC84C458-5A8A-4EC9-A1B3-15CC52DA2E91}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -214,7 +202,7 @@ Global {E5B3A633-A8F4-4D56-BB64-4A885E22B3B2} = {6CA9BC7A-0123-43E9-A26B-5FF0B9E01B08} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - EnterpriseLibraryConfigurationToolBinariesPathV6 = packages\EnterpriseLibrary.TransientFaultHandling.6.0.1304.0\lib\portable-net45+win+wp8;packages\EnterpriseLibrary.TransientFaultHandling.Data.6.0.1304.1\lib\NET45 SolutionGuid = {E996B5E6-49B2-4479-9DDE-455A40509F43} + EnterpriseLibraryConfigurationToolBinariesPathV6 = packages\EnterpriseLibrary.TransientFaultHandling.6.0.1304.0\lib\portable-net45+win+wp8;packages\EnterpriseLibrary.TransientFaultHandling.Data.6.0.1304.1\lib\NET45 EndGlobalSection EndGlobal diff --git a/src/Aardvark.Data.Photometry/Aardvark.Data.Photometry.csproj b/src/Aardvark.Data.Photometry/Aardvark.Data.Photometry.csproj deleted file mode 100644 index d0cd7774..00000000 --- a/src/Aardvark.Data.Photometry/Aardvark.Data.Photometry.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - netstandard2.0 - latest - - - ..\..\bin\Debug - ..\..\bin\Debug\netstandard2.0\Aardvark.Data.Photometry.xml - - - ..\..\bin\Release - ..\..\bin\Release\netstandard2.0\Aardvark.Data.Photometry.xml - - - \ No newline at end of file diff --git a/src/Aardvark.Data.Photometry/IESData.cs b/src/Aardvark.Data.Photometry/IESData.cs deleted file mode 100644 index f33a1433..00000000 --- a/src/Aardvark.Data.Photometry/IESData.cs +++ /dev/null @@ -1,118 +0,0 @@ -using Aardvark.Base; -using System; -using System.IO; -using System.Text; - -#pragma warning disable 1591 // missing XML comments - -namespace Aardvark.Data.Photometry -{ - public static class IESLabel - { - public static readonly Symbol Manufacturer = "MANUFAC"; - public static readonly Symbol TestReportNumber = "TEST"; - public static readonly Symbol LuminaireCatalog = "LUMCAT"; - public static readonly Symbol LuminaireDescription = "LUMINAIRE"; - public static readonly Symbol LampCatalog = "LAMPCAT"; - public static readonly Symbol LampDescription = "LAMP"; - public static readonly Symbol IssueDate = "ISSUEDATE"; - } - public enum IESformat - { - IES1986, - IES1991, - IES1995, - IES2002, - Unkown - } - - public enum IESUnitType - { - Feet = 1, - Meter = 2 - } - - public enum IESPhotometricType - { - /// - /// Type C photometry is normally used for architectural and roadway - /// luminaires. The polar axis of the photometric web coincides with the - /// vertical axis of the luminaire, and the 0-180 degree photometric plane - /// coincides with the luminaire's major axis (length). - /// - C = 1, - /// - /// Type B photometry is normally used for adjustable outdoor area and sports - /// lighting luminaires. The polar axis of the luminaire coincides with the - /// minor axis (width) of the luminaire, and the 0-180 degree photometric - /// plane coinicides with the luminaire's vertical axis. - /// - B = 2, - /// - /// Type A photometry is normally used for automotive headlights and signal - /// lights. The polar axis of the luminaire coincides with the major axis - /// (length) of the luminaire, and the 0-180 degree photometric plane - /// coinicides with the luminaire's vertical axis. - /// - A = 3, - } - - /// - /// Holds the data represented in an IES luminaire data file - /// http://lumen.iee.put.poznan.pl/kw/iesna.txt - /// - public class IESData - { - public static IESData FromFile(String filePath) - { - return IESParser.Parse(filePath); - } - - public static IESData FromStream(Stream stream) - { - return new IESParser().Parse(stream); - } - - public static IESData FromString(string data) - { - var stream = new MemoryStream(Encoding.UTF8.GetBytes(data)); - return FromStream(stream); - } - - public static IESData ParseMeta(String filePath) - { - return new IESParser().ParseMeta(filePath); - } - - public IESData() { } - - public IESformat Format { get; set; } - public Matrix Data { get; set; } - public double[] VerticleAngles { get; set; } - public double[] HorizontalAngles { get; set; } - public int HorizontalAngleCount { get; set; } - public int VerticalAngleCount { get; set; } - public SymbolDict Labels { get; set; } - public IESUnitType Unit { get; set; } - public IESPhotometricType Photometric { get; set; } - - /// - /// Luminous opening in C0-C180 plane. - /// - public double LuminaireWidth { get; set; } - - /// - /// Luminous opening in C90-C270 plane. - /// - public double LuminaireLength { get; set; } - - /// - /// Vertical luminous opening - /// - public double LuminaireHeight { get; set; } - public double CandelaMultiplier { get; set; } - public double LumenPerLamp { get; set; } - public int NumberOfLamps { get; set; } - public double InputWatts { get; set; } - } -} diff --git a/src/Aardvark.Data.Photometry/IESParser.cs b/src/Aardvark.Data.Photometry/IESParser.cs deleted file mode 100644 index 2ad11c91..00000000 --- a/src/Aardvark.Data.Photometry/IESParser.cs +++ /dev/null @@ -1,145 +0,0 @@ -using Aardvark.Base; -using System; -using System.IO; -using System.Linq; - -namespace Aardvark.Data.Photometry -{ - class IESParser : TextParser - { - public static IESData Parse(String filePath) - { - using (var stream = new FileStream(filePath, FileMode.Open)) - { - return new IESParser().Parse(stream); - } - } - - public IESData ParseMeta(String filePath) - { - using (var stream = new FileStream(filePath, FileMode.Open)) - { - using (var sr = new StreamReader(stream)) - { - return ReadMeta(sr); - } - } - } - - private IESData ReadMeta(StreamReader sr) - { - var ies = new IESData() - { - Labels = new SymbolDict() - }; - - String fileFormat = sr.ReadLine(); - // labels = new List<(string, string)>(); - - // in case of old format 1986 - if (fileFormat.StartsWith("[")) - { - var labelInput = LabelSplitForDict(fileFormat); - ies.Labels.Add(labelInput[0], labelInput[1]); - ies.Format = IESformat.IES1986; - } - else - { - if (fileFormat.Contains("1991")) ies.Format = IESformat.IES1991; - else if (fileFormat.Contains("1995")) ies.Format = IESformat.IES1995; - else if (fileFormat.Contains("2002")) ies.Format = IESformat.IES2002; - else ies.Format = IESformat.Unkown; - } - - String tempLabel = sr.ReadLine(); - while (tempLabel.StartsWith("[")) - { - var labelInput = LabelSplitForDict(tempLabel); - ies.Labels[labelInput[0]] = labelInput[1]; - tempLabel = sr.ReadLine(); - } - - var tilt = tempLabel; - tilt.Remove(0, 5); - // case parameters are availible - if (tilt == ("INCLUDE")) - { - var lampToLuminaireGeometry = ReadIntLine(sr); - var AnglesAndMultiplyingFactors = ReadIntLine(sr); - var angles = ReadDoubleLine(sr); - var multiplyingFactors = ReadDoubleLine(sr); - } - else if (tilt != ("NONE")) - { - var refFileName = tilt; - } // else it is NONE...no additional information is given - - String[] para = StringSplit(sr.ReadLine()); - if (para.Length == 10) - { - ies.NumberOfLamps = ParseInt(para[0]); - ies.LumenPerLamp = ParseDouble(para[1]); - ies.CandelaMultiplier = ParseDouble(para[2]); - ies.VerticalAngleCount = ParseInt(para[3]); - ies.HorizontalAngleCount = ParseInt(para[4]); - ies.Photometric = (IESPhotometricType)ParseInt(para[5]); - ies.Unit = (IESUnitType)ParseInt(para[6]); - ies.LuminaireWidth = ParseDouble(para[7]); - ies.LuminaireLength = ParseDouble(para[8]); - ies.LuminaireHeight = ParseDouble(para[9]); - } - else Console.WriteLine("ERROR - Parse ISE File (Parameters"); - - String[] ballast = StringSplit(sr.ReadLine()); - if (ballast.Length == 3) - { - double ballastFactor = ParseDouble(ballast[0]); - double ballastLampPhotometricFactor = ParseDouble(ballast[1]); - ies.InputWatts = ParseDouble(ballast[2]); - } - else Console.WriteLine("ERROR - Parse ISE File (Ballast)"); - - return ies; - } - - public IESData Parse(Stream stream) - { - using (var sr = new StreamReader(stream)) - { - var ies = ReadMeta(sr); - - // Vertical Angles - String[] verticalAngles = StringSplit(sr.ReadLine()); - while (verticalAngles.Length != ies.VerticalAngleCount) - { - verticalAngles = verticalAngles.Concat(StringSplit(sr.ReadLine())).ToArray(); - } - var vertAngleValues = verticalAngles.Map(str => ParseDouble(str)); - - ies.VerticleAngles = vertAngleValues; - - // Horizontal Angles - String[] horizontalAngles = StringSplit(sr.ReadLine()); - while (horizontalAngles.Length != ies.HorizontalAngleCount) - { - horizontalAngles = horizontalAngles.Concat(StringSplit(sr.ReadLine())).ToArray(); - } - var horizAngleValues = horizontalAngles.Map(str => ParseDouble(str)); - - ies.HorizontalAngles = horizAngleValues; - - // Candela Values - String[] candelaValues = StringSplit(sr.ReadLine()); - while (candelaValues.Length != ies.HorizontalAngleCount * ies.VerticalAngleCount) - { - candelaValues = candelaValues.Concat(StringSplit(sr.ReadLine())).ToArray(); - } - double[] candelaValuesParsed = candelaValues.Map(str => ParseDouble(str)); - - ies.Data = new Matrix(new V2i(ies.VerticalAngleCount, ies.HorizontalAngleCount)).SetByIndex(i => candelaValuesParsed[i]); - - return ies; - } - } - } -} \ No newline at end of file diff --git a/src/Aardvark.Data.Photometry/IntensityProfileSampler.cs b/src/Aardvark.Data.Photometry/IntensityProfileSampler.cs deleted file mode 100644 index 6ecebb3f..00000000 --- a/src/Aardvark.Data.Photometry/IntensityProfileSampler.cs +++ /dev/null @@ -1,162 +0,0 @@ -using Aardvark.Base; -using System.Linq; - -namespace Aardvark.Data.Photometry -{ - /// - /// Sampler for LightMeasurementData - /// The data is transformed to equidistant measurements so it can be addressed faster. - /// It holds a Matrix (with border) for CPU sampling and a PixImage for the GPU. - /// - public class IntensityProfileSampler - { - LightMeasurementData m_data; - - PixImage m_image; // texture for GPU sampling - Matrix m_matrixWithBorder; // matrix for CPU sampling (has two rows more to simplify filtering) - - V4f m_addressingParams; - V4f m_imageOffsetScale; - V2d m_scale; - - /// - /// Image for GPU sampling: Measuement data (re-sampled if not equidistance) - /// - public PixImage Image { get { return m_image; } } - - /// - /// Addressing parameters for GPU sampling: - /// Vector containing normalized scales and offsets: (vertical offset, vertical scale, horizontal offset, horizontal scale) - /// Vertical (Data Columns) = Gamma - /// Horizontal (Data Rows) = C-Plane - /// - public V4f AddressingParameters { get { return m_addressingParams; } } - - /// - /// Image offset and scale for GPU sampling: - /// Offset and scale from normlized vertical/horizontal spherical coordinates to texture coordinate with proper sub-pixel addressing - /// - public V4f ImageOffsetScale { get { return m_imageOffsetScale; } } - - /// - /// Returns the according measurement data - /// - public LightMeasurementData Data { get { return m_data; } } - - /// - /// Creates an IntensityProfileSampler for a LightMeasurementData - /// - public IntensityProfileSampler(LightMeasurementData data) - { - m_data = data; - - var equidistant = data.BuildEquidistantMatrix(); - - m_image = new PixImage(equidistant.Map(t => (float)t)); - - var originalMatrix = m_image.Matrix; - var matrixWithBorder = new Matrix(originalMatrix.SX + 2, originalMatrix.SY + 2) { FX = -1, FY = -1 }; - matrixWithBorder.Set(0.0f); - matrixWithBorder.SubCenter(new Border2l(1)).Set(originalMatrix); - - if (data.HorizontalSymmetry == HorizontalSymmetryMode.None) - { - var sx = originalMatrix.SX; - var sy = originalMatrix.SY; - - // Copy Last-row to Top-border - Matrix bottomRow = matrixWithBorder.SubMatrix(-1L, sy - 1, sx + 2, 1L); - matrixWithBorder.SubMatrix(-1L, -1L, sx + 2, 1L).Set(bottomRow); - - // Copy First-row to Bottom-border - Matrix topRow = matrixWithBorder.SubMatrix(-1L, 0L, sx + 2, 1L); - matrixWithBorder.SubMatrix(-1L, sy, sx + 2, 1L).Set(topRow); - } - - m_matrixWithBorder = matrixWithBorder; - - var scale = (V2d)m_matrixWithBorder.Size - 3; // 2 pixel larger size (border) and 1 for correct scale => -3 of matrixWithBorder / -1 of originalMatrix - - if (data.HorizontalSymmetry == HorizontalSymmetryMode.None) scale.Y++; // special case, where horizontal-symmetry needs wrap! - if (data.HorizontalSymmetry == HorizontalSymmetryMode.Full) scale.Y = 0; - - m_scale = scale; - - m_addressingParams = BuildAddressingParameters(); - - m_imageOffsetScale = BuildImageOffsetScale(); - - //m_texture = new PixTexture2d(new PixImageMipMap(m_image), false); - } - - private V4f BuildImageOffsetScale() - { - var size = m_image.Matrix.Size; - - float offsetVertical = 0.5f / size.X; // address to first texel center - float scaleVertical = (size.X - 1.0f) / size.X; // address to last texel center - - float offsetHorizontal = 0.5f / size.Y; // address to first texel center - float scaleHorizontal = (size.Y - 1.0f) / size.Y; // address to last texel center - - if (m_data.HorizontalSymmetry == HorizontalSymmetryMode.None) - { - // wrap first data row to 360° in case of measurement from 0 to e.g. 345 (LDT) - if (m_data.HorizontalAngles.Last() - m_data.HorizontalAngles.First() != 360) - scaleHorizontal = 1.0f; // wrap address to first texel center - } - - return new V4f(offsetVertical, scaleVertical, offsetHorizontal, scaleHorizontal); - } - - private V4f BuildAddressingParameters() - { - // in case of full symmetry its either possible to have 0 to (360-measureOffset) or 0 to 360 - // horizontal scale only relevant in half or quarter symmetry cases - var scaleHorizontal = (m_data.HorizontalSymmetry != HorizontalSymmetryMode.Full && m_data.HorizontalSymmetry != HorizontalSymmetryMode.None) ? 360.0f / Fun.Max(1, (m_data.HorizontalAngles.Last() - m_data.HorizontalAngles.First()).Abs()) : 1.0; - var scaleVertical = 180.0f / Fun.Max(1, (m_data.VerticalAngles.Last() - m_data.VerticalAngles.First()).Abs()); - var offsetHorizontal = -m_data.HorizontalAngles.First() / 360.0f; - var offsetVertical = -m_data.VerticalAngles.First() / 180.0f; - - return new V4f(offsetVertical, scaleVertical, offsetHorizontal, scaleHorizontal); - } - - /// - /// Returns the intensity for the given direction vector using linear interpolation in [cd]. - /// The direction vector is expected to be normalized. - /// The coordinate system is assumed to be: - /// [ 0, 0,-1] = Gamma 0° - /// [ 0, 0, 1] = Gamma 180° - /// [ 1, 0, 0] = C0 - /// [ 0, 1, 0] = C90 - /// [-1, 1, 0] = C180 - /// [ 0,-1, 0] = C270 - /// - public double GetIntensity(V3d dir) - { - var (c, gamma) = Photometry.CartesianToSpherical(dir); - return GetIntensity(c, gamma); - } - - /// - /// Returns the intensity for the angles using linear interpolation in [cd]. - /// The angles are assumed to be in radians and within their specified ranges. - /// c: [0, 2pi] - /// gamma: [0, pi] - /// - public double GetIntensity(double cInRadians, double gammaInRadians) - { - // Vertical angle: texture u coordinate - var vert = gammaInRadians * Constant.PiInv; // map to 0..1 - var u = Fun.Saturate((vert + m_addressingParams.X) * m_addressingParams.Y); - - // Horizontal angle: texture v coordinate - var horz = cInRadians * Constant.PiInv * 0.5; // map to 0..1 - var v = (1.0 - Fun.Abs(1.0 - Fun.Abs(((horz + m_addressingParams.Z) * m_addressingParams.W) % 2.0))); - - var uv = new V2d(u, v) * m_scale; // the +1 offset in Y because m_matrixWithBorder contains border is handled by the matrix FirstIndex (FX, FY) - - return m_matrixWithBorder.Sample4Clamped(uv, (t,a,b) => Fun.Lerp((float)t,a,b), (t, a, b) => Fun.Lerp((float)t, a, b)); - } - } -} diff --git a/src/Aardvark.Data.Photometry/LDTData.cs b/src/Aardvark.Data.Photometry/LDTData.cs deleted file mode 100644 index 8f8619d2..00000000 --- a/src/Aardvark.Data.Photometry/LDTData.cs +++ /dev/null @@ -1,107 +0,0 @@ -using Aardvark.Base; -using System; -using System.IO; -using System.Text; - -#pragma warning disable 1591 // missing XML comments - -namespace Aardvark.Data.Photometry -{ - public class LDTLampData - { - public int Number; - public string Type; - public double TotalFlux; - public string Color; - public string ColorRendering; - public double Wattage; - } - - /// - /// ELUMDAT Symmetry indicator - Isym - /// Specifies how the luminaire has been measured and how the data needs to be interpreted - /// - public enum LDTSymmetry - { - None = 0, // No symmetry - Vertical = 1, // Full symmetrically - C0 = 2, // Measurement data from 0 - 180 - C1 = 3, // Measurement data from 270 - 90 - Quarter = 4 // Measurement data from 0 - 90 - } - - /// - /// ELUMDAT Type indicator - Ityp - /// Indicates the luminaire type and describes its symmetry character. It does not necessarily mean that the measurement data - /// is also perfectly symmetrical according to this (e.g. Ityp = 1 does not force Isym = 1) - /// - public enum LDTItype - { - PointSource = 0, // point source with no symmetry - PointVerticalSymmetry = 1, // symmetry about the vertical axis - Linear = 2, // linear luminaire / can be subdivided in longitudinal and transverse directions - PointWithOtherSymmetry = 3 // point source with any other symmetry - } - - /// - /// Holds the data represented in an EULUMDATA luminaire data file - /// http://www.helios32.com/Eulumdat.htm - /// - public class LDTData - { - public static LDTData FromFile(String filename) - { - return LDTParser.Parse(filename); - } - - public static LDTData FromStream(Stream stream) - { - return new LDTParser().Parse(stream); - } - - public static LDTData FromString(string data) - { - var stream = new MemoryStream(Encoding.UTF8.GetBytes(data)); - return FromStream(stream); - } - - public static LDTData ParseMeta(string filename) - { - return new LDTParser().ParseMeta(filename); - } - - public LDTData() { } - - /// - /// Intensity distribution normalized to cd per 1000 lumen - /// - public Matrix Data { get; set; } - public double[] VerticleAngles { get; set; } - public double[] HorizontalAngles { get; set; } - public int PlaneCount { get; set; } - public double HorAngleStep { get; set; } - public int ValuesPerPlane { get; set; } - public double VertAngleStep { get; set; } - public LDTSymmetry Symmetry { get; set; } - public LDTItype Itype { get; set; } - public string CompanyName { get; set; } - public string LuminaireName { get; set; } - public string LuminaireNumber { get; set; } - public string FileName { get; set; } - public int LengthLuminaire { get; set; } - public int WidthLuminaire { get; set; } - public int HeightLuminare { get; set; } - public int LengthLuminousArea { get; set; } - public int WidthLuminousArea { get; set; } - public int HeightLuminousAreaC0 { get; set; } - public int HeightLuminousAreaC90 { get; set; } - public int HeightLuminousAreaC180 { get; set; } - public int HeightLuminousAreaC270 { get; set; } - public double DownwardFluxFraction { get; set; } - public double LightOutputRatioLuminaire { get; set; } - public double ConversionIntensity { get; set; } - public double Tilt { get; set; } - public LDTLampData[] LampSets { get; set; } - public double[] DirectRatios { get; set; } - } -} diff --git a/src/Aardvark.Data.Photometry/LDTParser.cs b/src/Aardvark.Data.Photometry/LDTParser.cs deleted file mode 100644 index 5241700d..00000000 --- a/src/Aardvark.Data.Photometry/LDTParser.cs +++ /dev/null @@ -1,146 +0,0 @@ -using Aardvark.Base; -using System; -using System.IO; - -namespace Aardvark.Data.Photometry -{ - class LDTParser : TextParser - { - public static LDTData Parse(String filePath) - { - using (var stream = new FileStream(filePath, FileMode.Open)) - { - return new LDTParser().Parse(stream); - } - } - - public LDTData ParseMeta(string filePath) - { - using (var stream = new FileStream(filePath, FileMode.Open)) - { - using (var sr = new StreamReader(stream)) - { - return ReadMeta(sr); - } - } - } - - private LDTData ReadMeta(StreamReader sr) - { - var ldt = new LDTData(); - // 1-5 - ldt.CompanyName = sr.ReadLine(); - ldt.Itype = (LDTItype)Enum.Parse(typeof(LDTItype), sr.ReadLine()); - ldt.Symmetry = (LDTSymmetry)Enum.Parse(typeof(LDTSymmetry), sr.ReadLine()); - ldt.PlaneCount = ReadIntLine(sr); - ldt.HorAngleStep = ReadDoubleLine(sr); - // 6-10 - ldt.ValuesPerPlane = ReadIntLine(sr); - ldt.VertAngleStep = ReadDoubleLine(sr); - var measurementReportNumber = sr.ReadLine(); - ldt.LuminaireName = sr.ReadLine(); - ldt.LuminaireNumber = sr.ReadLine(); - // 11-15 - ldt.FileName = sr.ReadLine(); - var dateUser = sr.ReadLine(); - ldt.LengthLuminaire = ReadIntLine(sr); - ldt.WidthLuminaire = ReadIntLine(sr); - ldt.HeightLuminare = ReadIntLine(sr); - // 16-20 - ldt.LengthLuminousArea = ReadIntLine(sr); - ldt.WidthLuminousArea = ReadIntLine(sr); - ldt.HeightLuminousAreaC0 = ReadIntLine(sr); - ldt.HeightLuminousAreaC90 = ReadIntLine(sr); - ldt.HeightLuminousAreaC180 = ReadIntLine(sr); - // 21-25 - ldt.HeightLuminousAreaC270 = ReadIntLine(sr); - ldt.DownwardFluxFraction = ReadDoubleLine(sr); - ldt.LightOutputRatioLuminaire = ReadDoubleLine(sr); - ldt.ConversionIntensity = ReadDoubleLine(sr); - ldt.Tilt = ReadDoubleLine(sr); - // 26 - SET INFO - var numberOfSets = ReadIntLine(sr); - ldt.LampSets = new LDTLampData[numberOfSets].SetByIndex(i => - { - var numberOfLamps = ReadIntLine(sr); - var typeOfLamps = sr.ReadLine(); - var totalLuminousFluxOfLamps = ReadDoubleLine(sr); - - var color = sr.ReadLine(); - //var colorAppearence = color[0]; - //var colorTemperature = color[1]; - - var colorRendering = sr.ReadLine(); - //var colorRenderingGroup = color[0]; - //var colorRenderingIndex = color[1]; - - var wattageInclBallasts = ReadDoubleLine(sr); - - return new LDTLampData() - { - Number = numberOfLamps, - Type = typeOfLamps, - TotalFlux = totalLuminousFluxOfLamps, - Color = color, - ColorRendering = colorRendering, - Wattage = wattageInclBallasts, - }; - }); - - return ldt; - } - - public LDTData Parse(Stream stream) - { - using (var sr = new StreamReader(stream)) - { - var ldt = ReadMeta(sr); - - // RATIO - ldt.DirectRatios = new double[10].SetByIndex(i => ReadDoubleLine(sr)); - - // ANGLES C (planes) - ldt.HorizontalAngles = new double[ldt.PlaneCount].SetByIndex(i => ReadDoubleLine(sr)); - - // ANGLES G (ON A PLANE) - ldt.VerticleAngles = new double[ldt.ValuesPerPlane].SetByIndex(i => ReadDoubleLine(sr)); - - // DATA - var mc1 = 1; - var mc2 = 1; - - switch (ldt.Symmetry) - { - case (LDTSymmetry.None): - mc1 = 1; - mc2 = ldt.PlaneCount; - break; - case (LDTSymmetry.Vertical): - mc1 = 1; - mc2 = 1; - break; - case (LDTSymmetry.C0): - mc1 = 1; - mc2 = ldt.PlaneCount / 2 + 1; - break; - case (LDTSymmetry.C1): - mc1 = 3 * (ldt.PlaneCount / 4) + 1; - mc2 = mc1 + ldt.PlaneCount / 2; - break; - case (LDTSymmetry.Quarter): - mc1 = 1; - mc2 = ldt.PlaneCount / 4 + 1; - break; - } - - int measurePlanes = (mc2 - mc1 + 1); - int dataLength = measurePlanes * ldt.ValuesPerPlane; - - var data = new double[dataLength].SetByIndex(i => ReadDoubleLine(sr)); - ldt.Data = Matrix.Create(data, ldt.ValuesPerPlane, measurePlanes); - - return ldt; - } - } - } -} \ No newline at end of file diff --git a/src/Aardvark.Data.Photometry/LightMeasurementData.cs b/src/Aardvark.Data.Photometry/LightMeasurementData.cs deleted file mode 100644 index 11430ce7..00000000 --- a/src/Aardvark.Data.Photometry/LightMeasurementData.cs +++ /dev/null @@ -1,499 +0,0 @@ -using Aardvark.Base; -using Aardvark.Base.Coder; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace Aardvark.Data.Photometry -{ - /// - /// Horizontal symmetry specification of photometric measurement data - /// - public enum HorizontalSymmetryMode - { - /// No Symmetry - None, - /// Full symmetrically - Full, - /// Mirrored along one plane (0-180 or -90 to 90 or 90 to 270) - Half, - /// 0 - 90 - Quarter, - /// Measurement angles do not match any common symmetry case - Unknown - } - - /// - /// Vertical data range specification of photometric measurements - /// - public enum VerticalRangeMode - { - /// 0-180 - Full, - /// 0 - 90 (e.g. Ceiling-mounted-light) - Bottom, - /// 90 - 180 (e.g. Floor-mounted-light) - Top, - } - - /// - /// Unified representation of photometry measurement data. - /// - [RegisterTypeInfo(Version=4)] - public partial class LightMeasurementData : IFieldCodeable, IAwakeable - { - /// - /// Specified luminous flux in lumen supplied by the photometric report. - /// - public double LumFlux; - - /// - /// Absolute measured intensities in cd [Vertical, Horizontal] - /// Integral of these values is supposed to give the specified luminous flux. - /// - /// X = VerticalAngles, Y = HorizontalAngles (C-Planes) - /// - /// 0° 5° 10° ... - /// --------------- - /// C0 | x x x ... - /// C30 | x x x ... - /// C60 | x x x ... - /// . | . . . . - /// . | . . . . - /// - /// - public Matrix Intensities; - - /// - /// Horizontal symmetry type - /// - public HorizontalSymmetryMode HorizontalSymmetry; - - /// - /// Vertical symmetry type - /// - public VerticalRangeMode VerticalRange = VerticalRangeMode.Full; - - /// - /// Horizontal angles of measurement in degree in counter clockwise order. - /// Typical cases of measurement angles are: - /// Full symmetry - single value annotated as 0° - /// Complete measurement (no symmetry) - [0, 360-measureDistance] or [0, 360] in some IES files - /// Symmetry across C0-C180 plane - [0, 180] - /// Symmetry across C90-C270 plane - [270, 90] in LDT or [90, 270] in IES - /// Symmetry across C0-C180 and C90-C270 planes - [0, 90] - /// - public double[] HorizontalAngles; - - /// - /// Vertical angles of measurement in degree where 0 is pointing to the bottom and 180 to the top. - /// Typical measurement angles ranges are [0, 180], [0, 90] and [90, 180]. - /// - public double[] VerticalAngles; - - /// - /// Name of the measurement data (LuminaireDescription or LuminaireName) - /// - public string Name; - - /// - /// Creates an empty LightMeasurementData (need to be initialized programmatically) - /// - public LightMeasurementData() { } - - /// - /// Create a LightMeasurementData from IES data - /// - public LightMeasurementData(IESData ies) - { - Name = ies.Labels.Get(IESLabel.LuminaireDescription, null); - - Intensities = ies.Data; - - var firstHoriz = ies.HorizontalAngles[0]; - var lastHoriz = ies.HorizontalAngles[ies.HorizontalAngleCount - 1]; - var firstVert = ies.VerticleAngles[0]; - var lastVert = ies.VerticleAngles[ies.VerticalAngleCount - 1]; - - HorizontalAngles = ies.HorizontalAngles; - VerticalAngles = ies.VerticleAngles; - - var range = (firstHoriz - lastHoriz).Abs(); - if (HorizontalAngles.Length == 1) HorizontalSymmetry = HorizontalSymmetryMode.Full; - else if (range == 90) HorizontalSymmetry = HorizontalSymmetryMode.Quarter; - else if (range == 180) HorizontalSymmetry = HorizontalSymmetryMode.Half; - else if (range > 180) HorizontalSymmetry = HorizontalSymmetryMode.None; - // NOTE: this is an error in the draft IES LM-63 - 1995 standard, because - // the 360 - degree plane is coincident with the 0 - degree plane. It - // should read "greater than 180 degrees and less than 360 degrees" - else { HorizontalSymmetry = HorizontalSymmetryMode.Unknown; Report.Warn("IES-File {0} has a non-compatible HorizontalSymmetryMode", Name); } - - if (firstVert == 0 && lastVert == 180) VerticalRange = VerticalRangeMode.Full; - else if (firstVert == 0 && lastVert == 90) VerticalRange = VerticalRangeMode.Bottom; - else if (firstVert == 90 && lastVert == 180) VerticalRange = VerticalRangeMode.Top; - else Report.Warn("IES-File {0} has a non-valid VerticalRangeMode", Name); - - LumFlux = ies.NumberOfLamps * ies.LumenPerLamp * ies.CandelaMultiplier; - } - - /// - /// Create a LightMeasurementData from LDT data - /// - public LightMeasurementData(LDTData ldt) - { - Name = ldt.LuminaireName; - - var totalLampFlux = ldt.LampSets.Sum(x => x.TotalFlux); - - var lor = ldt.LightOutputRatioLuminaire / 100; - LumFlux = totalLampFlux * lor; - - // Intensity data of an EULUMDAT file is stored in cd per 1000 lumen - // -> scale intensities to get absolute intensity distribution - - var scale = totalLampFlux / 1000; // NOTE: using totalLampFlux here is the proper scale according to the validation in PhotometryTests.LumFluxTest - Intensities = scale != 1.0 ? ldt.Data.Map(x => x * scale) : ldt.Data; - - HorizontalSymmetry = ConvertSymmetry(ldt.Symmetry); - - // LDT has all horizontal angles written, possible more that the data array -> filter in that case - HorizontalAngles = ldt.Symmetry == LDTSymmetry.C0 ? FilterAnglesBetween(ldt.HorizontalAngles, 0, 180) - : ldt.Symmetry == LDTSymmetry.C1 ? FilterAnglesBetween(ldt.HorizontalAngles, 270, 359.9).Concat(FilterAnglesBetween(ldt.HorizontalAngles, 0, 90)).ToArray() - : ldt.Symmetry == LDTSymmetry.Quarter ? FilterAnglesBetween(ldt.HorizontalAngles, 0, 90) - : ldt.HorizontalAngles; - - VerticalAngles = ldt.VerticleAngles; - - if (ldt.VerticleAngles.First() == 0 && ldt.VerticleAngles.Last() == 180) VerticalRange = VerticalRangeMode.Full; - else if (ldt.VerticleAngles.First() == 0 && ldt.VerticleAngles.Last() == 90) VerticalRange = VerticalRangeMode.Bottom; - else if (ldt.VerticleAngles.First() == 90 && ldt.VerticleAngles.Last() == 180) VerticalRange = VerticalRangeMode.Top; - else Report.Warn("LDT-File {0} has a non-valid VerticalRangeMode", Name); - } - - /// - /// Checks wheter the measurment data is equidistant. - /// - public bool IsEquidistant - { - get { return !IsNonEquidistant(HorizontalAngles) && !IsNonEquidistant(VerticalAngles); } - } - - /// - /// Calculates the minimal angular vertical measure distance in degrees - /// - public double MinVerticalMeasureDistance - { - get { return CalcMinAngleStep(VerticalAngles); } - } - - /// - /// Calculates the minimal angular horizontal measure distance in degrees - /// - public double MinHorizontalMeasureDistance - { - get { return CalcMinAngleStep(HorizontalAngles); } - } - - private int GetPlaneIndex(double plane) - { - // NOTE: throw IndexNotFound exception - // plane must be [0; 360] - - // early exit if there is full symmetry - if (this.HorizontalSymmetry == HorizontalSymmetryMode.Full) - return 0; - - var dataPlane = plane % 360.0; - // only special case if there is no full 360° measurement - if (this.HorizontalSymmetry != HorizontalSymmetryMode.None) - { - var first = this.HorizontalAngles.First(); - var last = this.HorizontalAngles.Last(); - var range = (first - last).Abs(); // measurement 270-90 - - //var z = -first / 360.0f; - //var w = 360.0 / range; - - //var t = dataPlane / 360.0; - //var v = 1.0 - Fun.Abs(1.0f - Fun.Abs(((t + z) * w) % 2.0)); - //var a = (v * range + first) % 360; - - var a2 = range - Fun.Abs(range - Fun.Abs((dataPlane - first) % (range * 2))); // mirror and repeat if outside range - dataPlane = (a2 + first) % 360; - } - - // get index of measurement data - return this.HorizontalAngles.IndexOf(dataPlane); - } - - /// - /// Returns photometric measurement values along a C-Plane with (vertical-angle in degrees, intensity). - /// The plane [0; 360] must be one of the horizontal measurement planes of the photometric report, - /// interpolated values are not supported. - /// - /// Example: plane=0 gives C0-180 360° measurement values - /// plane=15 gives C15-195 measurement values - /// plane=180 gives C180-0 measurement values (left-right mirrored values of C0-180) - /// - public List<(double, double)> GetCPlane(double plane) - { - var index = GetPlaneIndex(plane); - - // c-plane values: - var cPlaneValues = Intensities.GetRow(index); - - var values = new List<(double, double)>((int)cPlaneValues.Count * 2 - 2); - - int i = 0; - foreach (var value in cPlaneValues.Elements) - { - values.Add((VerticalAngles[i++], value)); - } - - // stitch second half of c-plane to angle-value pairs (+180°) - - var index180 = GetPlaneIndex(plane + 180); - var cPlaneValues180 = Intensities.GetRow(index180); - cPlaneValues180 = cPlaneValues180.SubVector(1, cPlaneValues180.Size - 2); // skip angle at top and bottom (would be twice otherwise) - - i = 1; - foreach (var value in cPlaneValues180.Elements) - { - values.Add((-VerticalAngles[i++], value)); - } - - return values; - } - - /// - /// Builds an equidistant measurement data matrix. - /// NOTE: The symmetry type is the same. - /// NOTE: Data will be re-sampled at the smallest horizontal and vertical angular measured distance - /// - /// Equidistant measurement data or original in case it is already equidistant - public Matrix BuildEquidistantMatrix() - { - var result = Intensities; - - if (IsNonEquidistant(HorizontalAngles)) result = FixNonEquidistantAngleStep(HorizontalAngles, result, true); - if (IsNonEquidistant(VerticalAngles)) result = FixNonEquidistantAngleStep(VerticalAngles, result, false); - - return result; - } - - private static double CalcMinAngleStep(double[] angles) - { - var minStep = Double.MaxValue; - - for (var i = 0; i < angles.Length - 1; i++) - { - var diff = AngleDifference(angles[i + 1], angles[i]); - if (diff < minStep) minStep = diff; - } - - if (minStep <= 0) - throw new Exception(); - - return minStep; - } - - private Matrix FixNonEquidistantAngleStep(double[] angles, Matrix data, bool horizontalFix) - { - var minStep = CalcMinAngleStep(angles); - - var valuesPerPlane = data.SX; - var planeCount = data.SY; - - var elementCount = (long)((AngleDifference(angles[angles.Length - 1], angles[0])) / minStep) + 1; - - if (elementCount >= 4096) - { - elementCount = 4096; - Report.Warn("Repairing Non-Equidistant Photometry Steps results into too many elements (Max. Elements per C-Plane is 4096)!"); - } - - if (horizontalFix) planeCount = elementCount; - else valuesPerPlane = elementCount; - - var tempMatrix = new Matrix(valuesPerPlane, planeCount); - - if (horizontalFix) - { - // Horizontal interpolation - for (var valueOnPlane = 0; valueOnPlane < valuesPerPlane; valueOnPlane++) - { - var searchIndex = 0; - - for (var plane = 0; plane < planeCount; plane++) - { - var myAngle = angles[0] + plane * minStep; - - // check if upper lookupAngle is to small - if (myAngle > angles[searchIndex + 1]) searchIndex++; - - var refLower = angles[searchIndex]; - var refUpper = angles[searchIndex + 1]; - - var lowerV = data[valueOnPlane, searchIndex]; - var upperV = data[valueOnPlane, searchIndex + 1]; - - var t = (myAngle - refLower) / (refUpper - refLower); - - var value = Fun.Lerp(t, lowerV, upperV); - - tempMatrix[valueOnPlane, plane] = value; - } - } - } - else - { - // Vertical interpolation - for (var plane = 0; plane < planeCount; plane++) - { - var searchIndex = 0; - - for (var valueOnPlane = 0; valueOnPlane < valuesPerPlane; valueOnPlane++) - { - var myAngle = angles[0] + valueOnPlane * minStep; - - // check if upper lookupAngle is to small - if (myAngle > angles[searchIndex + 1]) searchIndex++; - - var refLower = angles[searchIndex]; - var refUpper = angles[searchIndex + 1]; - - var lowerV = data[searchIndex, plane]; - var upperV = data[searchIndex + 1, plane]; - - var t = (myAngle - refLower) / (refUpper - refLower); - - var value = Fun.Lerp(t, lowerV, upperV); - - tempMatrix[valueOnPlane, plane] = value; - } - } - } - - return tempMatrix; - } - - /// - /// Calculate the signed angular distance between a and b - /// - private static double AngleDifference(double a, double b) - { - // TODO: move to Aardvark.Base - var diff = a - b; - var mod = diff - 360 * Fun.Round(diff / 360); - return mod; - } - - private bool IsNonEquidistant(double[] angles) - { - if (angles.Length < 3) return false; - - var minStep = AngleDifference(angles[1], angles[0]); - - for (var i = 1; i < angles.Length - 1; i++) - { - var diff = AngleDifference(angles[i + 1], angles[i]); - if (diff != minStep) return true; - } - - return false; - } - - private double[] FilterAnglesBetween(double[] angles, double lower, double upper) - { - //return angles.SkipWhile(v => v < lower).TakeWhile(v => v <= upper).ToArray(); - - var list = new List(); - - for (var i = 0; i < angles.Length; i++) - { - var angle = angles[i]; - if (angle >= lower && angle <= upper) list.Add(angle); - } - - return list.ToArray(); - } - - #region IFieldCodeable Members - /// - /// Implementation of FieldCoders for serialization - /// - public IEnumerable GetFieldCoders(int coderVersion) - { - yield return new FieldCoder(0, "HorizontalSymmetry", (c, o) => c.CodeT(ref ((LightMeasurementData)o).HorizontalSymmetry)); - yield return new FieldCoder(1, "VerticalRange", (c, o) => c.CodeT(ref ((LightMeasurementData)o).VerticalRange)); - yield return new FieldCoder(2, "Intensities", (c, o) => c.CodeMatrix_of_Double_(ref ((LightMeasurementData)o).Intensities)); - yield return new FieldCoder(3, "Name", (c, o) => c.CodeString(ref ((LightMeasurementData)o).Name)); - yield return new FieldCoder(4, "CalculatedLumFlux", 1, 2, (c, o) => c.CodeDouble(ref ((LightMeasurementData)o).LumFlux)); - yield return new FieldCoder(5, "LumFlux", 2, int.MaxValue, (c, o) => c.CodeDouble(ref ((LightMeasurementData)o).LumFlux)); - yield return new FieldCoder(6, "HorizontalAngles", 3, int.MaxValue, (c, o) => c.CodeDoubleArray(ref ((LightMeasurementData)o).HorizontalAngles)); - yield return new FieldCoder(7, "VerticalAngles", 3, int.MaxValue, (c, o) => c.CodeDoubleArray(ref ((LightMeasurementData)o).VerticalAngles)); - } - #endregion - - /// - /// Loads an IES or LDT (EULUMDAT) photometry file. - /// - public static LightMeasurementData FromFile(string fileName) - { - if (!File.Exists(fileName)) - throw new Exception(String.Format("Photometry file does not exist: \"{0}\"", fileName)); - - if (fileName.ToLowerInvariant().EndsWith("ldt")) - { - return new LightMeasurementData(LDTData.FromFile(fileName)); - } - else if (fileName.ToLowerInvariant().EndsWith("ies")) - { - return new LightMeasurementData(IESData.FromFile(fileName)); - } - else - { - throw new Exception(String.Format("Photometry format of \"{0}\" is not supported.", Path.GetFileName(fileName))); - } - } - - /// - /// Callback after de-serialization in order to perform version conversion. - /// - public void Awake(int codedVersion) - { - if (codedVersion < 4) - { - var ldtSymmetry = (LDTSymmetry)this.HorizontalSymmetry; - this.HorizontalSymmetry = ConvertSymmetry(ldtSymmetry); - - var voffset = this.VerticalRange == VerticalRangeMode.Top ? 90 : 0; - var vdelta = (this.VerticalRange == VerticalRangeMode.Full ? 180 : 90) / (double)Fun.Max(this.Intensities.SX - 1, 1); - var hoffset = ldtSymmetry == LDTSymmetry.C1 ? 90 : 0; - var hdelta = (ldtSymmetry == LDTSymmetry.C0 || ldtSymmetry == LDTSymmetry.C1 ? 180 : - ldtSymmetry == LDTSymmetry.Quarter ? 90 : - ldtSymmetry == LDTSymmetry.None ? 0 : 360) / (double)Fun.Max(this.Intensities.SY - 1, 1); - this.VerticalAngles = new double[this.Intensities.SX].SetByIndex(i => voffset + vdelta * i); - this.HorizontalAngles = new double[this.Intensities.SY].SetByIndex(i => hoffset + hdelta * i); - - if (ldtSymmetry == LDTSymmetry.C1) - this.HorizontalAngles = this.HorizontalAngles.Map(x => x < 180 ? x + 180 : x - 180); - - // in early versions the LumFlux was not saved -> force calculation, does not perfectly match the rounded LumFlux specified in the meta data of LDT or IES - if (codedVersion == 0) - { - var equidistanceData = BuildEquidistantMatrix(); - LumFlux = CalculateLumFlux(equidistanceData, this.VerticalRange); - } - } - } - - static HorizontalSymmetryMode ConvertSymmetry(LDTSymmetry sym) - { - return sym == LDTSymmetry.None ? HorizontalSymmetryMode.None : - sym == LDTSymmetry.C0 || sym == LDTSymmetry.C1 ? HorizontalSymmetryMode.Half : - sym == LDTSymmetry.Quarter ? HorizontalSymmetryMode.Quarter : HorizontalSymmetryMode.Full; - } - } -} diff --git a/src/Aardvark.Data.Photometry/Photometry.cs b/src/Aardvark.Data.Photometry/Photometry.cs deleted file mode 100644 index 2ddbf81f..00000000 --- a/src/Aardvark.Data.Photometry/Photometry.cs +++ /dev/null @@ -1,58 +0,0 @@ -using Aardvark.Base; -using System; -using System.Collections.Generic; -using System.Text; - -namespace Aardvark.Data.Photometry -{ - /// - /// Utility functions for using photometic data - /// - public static class Photometry - { - /// - /// Returns the direction vector of the given c and gamma angles. - /// The angles are expected to be in radians. - /// The coordinate system is defined as: - /// [ 0, 0,-1] = Gamma 0° - /// [ 0, 0, 1] = Gamma 180° - /// [ 1, 0, 0] = C0 - /// [ 0, 1, 0] = C90 - /// [-1, 1, 0] = C180 - /// [ 0,-1, 0] = C270 - /// NOTE: gamma/theta is mapped differntly than in Aardvark Conversion.CartesianFromSpherical - /// - public static V3d SphericalToCartesian(double cInRadians, double gammaInRadians) - { - var s = gammaInRadians.Sin(); - return new V3d(cInRadians.Cos() * s, cInRadians.Sin() * s, -gammaInRadians.Cos()); - } - - /// - /// Returns (c, gamma) angles in radians of the direction vector (normalized). - /// The coordinate system is defined as: - /// [ 0, 0,-1] = Gamma 0° - /// [ 0, 0, 1] = Gamma 180° - /// [ 1, 0, 0] = C0 - /// [ 0, 1, 0] = C90 - /// [-1, 1, 0] = C180 - /// [ 0,-1, 0] = C270 - /// NOTE: gamma/theta is mapped differntly than in Aardvark Conversion.CartesianFromSpherical - /// - public static (double, double) CartesianToSpherical(V3d v) - { - // [0,0,-1] = 0° - // [0,0, 1] = 180° - var gamma = Constant.Pi - Fun.AcosClamped(v.Z); - - // C0: atan2( 0 1) = 0 - // C90: atan2( 1 0) = 90 - // C180: atan2( 0 -1) = 180/-180 - // C270: atan2(-1 0) = -90 - // normalize [-pi..pi] to [0..1] -> invert vector and add 180° - var c = Fun.Atan2(-v.Y, -v.X) + Constant.Pi; // atan2: -pi..pi -> 0..2pi - - return (c, gamma); - } - } -} diff --git a/src/Aardvark.Data.Photometry/PhotometryDataCalculations.cs b/src/Aardvark.Data.Photometry/PhotometryDataCalculations.cs deleted file mode 100644 index f6cb3a0a..00000000 --- a/src/Aardvark.Data.Photometry/PhotometryDataCalculations.cs +++ /dev/null @@ -1,385 +0,0 @@ -using Aardvark.Base; -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices.ComTypes; -using System.Text; - -namespace Aardvark.Data.Photometry -{ - public partial class LightMeasurementData - { - /// - /// Calculates the luminous flux from an equidistant measurement dataset - /// - public static double CalculateLumFlux(Matrix equiDistantData, VerticalRangeMode vertRangeMode) - { - double sum = 0.0; - double weightSum = 0.0; - double vFact = 0.0; - //double vFact1 = 0.0; - - double angleScale = vertRangeMode == VerticalRangeMode.Full ? 1.0 : 0.5; - double angleOffset = vertRangeMode == VerticalRangeMode.Top ? 0.5 : 0.0; - - //Report.BeginTimed("CalcLumFlux"); - - // each vertical angle has to be weighted according to circumference of at "equator" - var mtxInfo = equiDistantData.Info; - long xs = mtxInfo.DSX, xj = mtxInfo.JXY; - long ys = mtxInfo.DSY, yj = mtxInfo.JY0; - long i = mtxInfo.FirstIndex; - for (long xe = i + xs, x = mtxInfo.FX; i != xe; i += xj, x++) - { - // calc cos of vAngle - var vAngle = x / (double)(equiDistantData.Size.X - 1); // weight bottom/to with slightly offseted angles -> otherwise they would have weight=0 - vAngle = vAngle * angleScale + angleOffset; - - vFact = Fun.Sin(vAngle * Constant.Pi); // radius of circle -> circumference = 2r*PI - - weightSum += vFact * equiDistantData.Size.Y; - - // Calculate weight for interpolated value (between x and x+1 -> x+0.5) - //var vAngle1 = (x + 0.5) / (double)(Raw.Size.X - 1); // weight bottom/to with slightly offseted angles -> otherwise they would have weight=0 - //vAngle1 = vAngle1 * angleScale + angleOffset; - - //vFact1 = Fun.Sin(vAngle1 * Constant.Pi); // radius of circle -> circumference = 2r*PI - - //weightSum += vFact1 * Raw.Size.Y; - - for (long ye = i + ys, y = mtxInfo.FY; i != ye; i += yj, y++) - { - var value = equiDistantData[x, y]; - sum += value * vFact; - - //if (x + 1 < Raw.Size.X) - //{ - // var value1 = Raw[x + 1, y]; - // sum += (value1 + value) * 0.5 * vFact1; - //} - } - } - - //Report.End(); - - var lumFlux = sum / weightSum; - - if (vertRangeMode != VerticalRangeMode.Full) - lumFlux /= 2; // half the angles are zero -> average flux over sphere is half - return lumFlux * Constant.PiTimesFour; - } - - /// - /// Calculates the luminous flux from the measurement data. - /// - public double CalculateLumFlux() - { - var lumFlux = 0.0; - - double segmentAreaFull = 0.0; // full sphere segment area till current angle when looping over data - - // weight factor for each data segment - var hs = this.HorizontalSymmetry; - var connectToFirst = hs != HorizontalSymmetryMode.Half && hs != HorizontalSymmetryMode.Quarter; - var segCount = this.Intensities.Size.Y; // number of c-planes data rows - if (!connectToFirst) segCount -= 1; - var dataAreaFactor = 1.0 / segCount; - - var weight0 = 0.0; - - var mtxInfo = this.Intensities.Info; - long xs = mtxInfo.DSX, xj = mtxInfo.JXY; - long ys = mtxInfo.DSY, yj = mtxInfo.JY0; - long i = mtxInfo.FirstIndex; - for (long xe = i + xs, x = mtxInfo.FX; i != xe; i += xj, x++) - { - // x: vertical angle [0, 180] or [0, 90] or [90, 180] - if (x == 0) { i += ys; continue; } - - var phi = this.VerticalAngles[x] * Constant.RadiansPerDegree; - - // calculate area of full segment till theta1 - var a = Fun.Sin(phi); - var h = 1 - Fun.Cos(phi); - var segmentAreaPhi1 = Constant.Pi * (a.Square() + h.Square()); - - // area of current segment - var dataSegmentArea = (segmentAreaPhi1 - segmentAreaFull) * dataAreaFactor; - - segmentAreaFull = segmentAreaPhi1; - - // weight data points by circumference of measurement angle - var weight1 = a; // circumference is actually 2pi * r, but the constant factor can be omitted when calculating the weighed average - - // if a weight is 0, this means we are the pole (0° or 180°) -> give half weight to pole sample - if (weight0 == 0) weight0 = weight1 * 0.5; - if (weight1 == 0) weight1 = weight0 * 0.5; - - var weightNorm = 1.0 / ((weight0 + weight1) * 2); // 1.0 / weightSum -> x2 as there are two samples each - - var iTheta0 = 0.0; - // y: horizontal angle / c-plane [0] or [0-360] or [0-90] or [0-180] or [-90-90] or [90-270] - for (long ye = i + ys, y = mtxInfo.FY; i != ye; i += yj, y++) - { - var iTheta1 = this.Intensities[x, y] * weight1 + this.Intensities[x - 1, y] * weight0; - if (y > 0) - { - var iavg = (iTheta0 + iTheta1) * weightNorm; - lumFlux += iavg * dataSegmentArea; - } - - iTheta0 = iTheta1; - } - - if (connectToFirst) - { - // connect to first data row - var iTheta1 = this.Intensities[x, 0] * weight1 + this.Intensities[x - 1, 0] * weight0; - var iavg = (iTheta0 + iTheta1) * weightNorm; - lumFlux += iavg * dataSegmentArea; - } - - weight0 = weight1; - } - - return lumFlux; - } - - /// - /// Retrieves the major intensity and direction angles of the photometric measurement. - /// - /// (Intensity, C-Plane in degrees, angle Gamma in degrees) - public (double, double, double) CalculateMajor() - { - V2l majorIndex = V2l.Zero; - var majorInt = 0.0; - - Intensities.ForeachCoord(crd => - { - var value = Intensities[crd]; - - if (value > majorInt) - { - majorInt = value; - majorIndex = crd; - } - }); - - var gamma = VerticalAngles[majorIndex.X]; - var cplane = HorizontalAngles[majorIndex.Y]; - - return (majorInt, cplane, gamma); - } - - /// - /// Finds the maximum intensity and direction of a given measurement plane. - /// The specified plane must be one of the horizontal measurement angles, - /// interpolated c0 planes are not supported. - /// - /// [0, 360] - /// (Intensity, angle Gamma in degrees) - public (double, double) CalculateCMajor(double plane) - { - var index = GetPlaneIndex(plane); - - // c-plane values: - var cPlaneValues = Intensities.GetRow(index); - var cMaxIndex = cPlaneValues.Elements.MaxIndex(); - var cMaxValue = cPlaneValues[cMaxIndex]; - - var gamma = VerticalAngles[cMaxIndex]; - - return (cMaxValue, gamma); - } - - /// - /// Calculates luminous flux per zone - /// Zones: 0-10, 10-20, 20-30, ... 170-180 - /// Gives a total of 18 zones. - /// - /// Array of length 18 containing luminous flux per zone - public double[] CalculateZones() - { - // zones 0-10, 10-20, 20-30, ... 170-180 - var zones = new double[18]; - - double segmentAreaFull = 0.0; // full sphere segment area till current angle when looping over data - - // weight factor for each data segment - var hs = this.HorizontalSymmetry; - var connectToFirst = hs != HorizontalSymmetryMode.Half && hs != HorizontalSymmetryMode.Quarter; - var segCount = this.Intensities.Size.Y; // number of c-planes data rows - if (!connectToFirst) segCount -= 1; - var dataAreaFactor = 1.0 / segCount; - - bool changeZone = false; - bool repeatVertical = false; - int zone = 0; - - var weight0 = 0.0; - - var mtxInfo = this.Intensities.Info; - long xs = mtxInfo.DSX, xj = mtxInfo.JXY; - long ys = mtxInfo.DSY, yj = mtxInfo.JY0; - long i = mtxInfo.FirstIndex; - for (long xe = i + xs, x = mtxInfo.FX; i != xe; i += xj, x++) - { - // x: vertical angle [0, 180] or [0, 90] or [90, 180] - if (x == 0) { i += ys; continue; } - - var phi = this.VerticalAngles[x]; - - if (changeZone) { zone++; changeZone = false; } - - // clamp theta1 to zone limit - if (phi > (zone + 1) * 10) - { - phi = (zone + 1) * 10; - repeatVertical = true; - } - - changeZone = phi == (zone + 1) * 10; - - phi *= Constant.RadiansPerDegree; - // calculate area of full segment till theta1 - var a = Fun.Sin(phi); - var h = 1 - Fun.Cos(phi); - var segmentAreaPhi1 = Constant.Pi * (a.Square() + h.Square()); - - // area of current segment - var dataSegmentArea = (segmentAreaPhi1 - segmentAreaFull) * dataAreaFactor; - - segmentAreaFull = segmentAreaPhi1; - - // weight data points by circumference of measurement angle - var weight1 = a; // circumference is actually 2pi * r, but the constant factor can be omitted when calculating the weighed average - - // if a weight is 0, this means we are the pole (0° or 180°) -> give half weight to pole sample - if (weight0 == 0) weight0 = weight1 * 0.5; - if (weight1 == 0) weight1 = weight0 * 0.5; - - var weightNorm = 1.0 / ((weight0 + weight1) * 2); // 1.0 / weightSum -> x2 as there are two samples each - - var iTheta0 = 0.0; - // y: horizontal angle / c-plane [0] or [0-360] or [0-90] or [0-180] or [-90-90] or [90-270] - for (long ye = i + ys, y = mtxInfo.FY; i != ye; i += yj, y++) - { - var iTheta1 = this.Intensities[x, y] * weight1 + this.Intensities[x - 1, y] * weight0; - if (y > 0) - { - var iavg = (iTheta0 + iTheta1) * weightNorm; - zones[zone] += iavg * dataSegmentArea; - } - - iTheta0 = iTheta1; - } - - if (connectToFirst) - { - // connect to first data row - var iTheta1 = this.Intensities[x, 0] * weight1 + this.Intensities[x - 1, 0] * weight0; - var iavg = (iTheta0 + iTheta1) * weightNorm; - zones[zone] += iavg * dataSegmentArea; - } - - weight0 = weight1; - - if (repeatVertical) - { - repeatVertical = false; - i -= ys; - i -= xj; - x--; - } - } - - return zones; - } - } - - /// - /// Collection of IntensityProfileSampler extension - /// - public static class PhotometryDataCalculations - { - /// - /// Samples the luminous flux per zone using an IntensityProfileSampler. - /// The result should be approximately equal to CalculateZones. - /// A sampleCount for at least 8192 should be used for reliable results. - /// Zones: 0-10, 10-20, 20-30, ... 170-180 - /// Gives a total of 18 zones. - /// - /// Array of length 18 containing luminous flux per zone - public static double[] SampleZones(this IntensityProfileSampler sampler, int sampleCount) - { - // zones 0-10, 10-20, 20-30, ... 170-180 - var zones = new double[18]; - - var rnd = new RandomSystem(18); - var rndSeries = new HaltonRandomSeries(2, rnd); - - for (int i = 0; i < sampleCount; i++) - { - var v = RandomSample.Spherical(rndSeries, 0); - - var phi = Fun.AcosClamped(-v.Z); // 0 to pi [0, 180°] - - var zi = Fun.Min((int)(phi * 18 * Constant.PiInv), 17); - - zones[zi] += sampler.GetIntensity(v); - } - - var norm = Constant.PiTimesFour / sampleCount; - zones.Apply(x => x * norm); - - return zones; - } - - /// - /// Calculates the luminous flux by using sampling to integrate luminous intensity function. - /// - public static double SampleLumFlux(this IntensityProfileSampler sampler, int sampleCount) - { - var rnd = new RandomSystem(18); - var rndSeries = new HaltonRandomSeries(2, rnd); - - var lumFlux = 0.0; - for (int i = 0; i < sampleCount; i++) - { - var v = RandomSample.Spherical(rndSeries, 0); - lumFlux += sampler.GetIntensity(v); - } - - lumFlux *= Constant.PiTimesFour / sampleCount; - - return lumFlux; - } - - /// - /// Creates a cube texture representing the photometric measurement. - /// The cubemap resolution will be approximately twice the sampling rate of the original data. - /// The cubemap layout will be right-handed, z-up, with [XN YP XP YN ZP ZN] - /// - public static PixCube GetCubeTexture(this IntensityProfileSampler sampler) - { - var data = sampler.Data; - var space = Fun.Min(data.MinVerticalMeasureDistance, data.MinHorizontalMeasureDistance); - - int cubeRes; - if (space >= 45.0) - { - cubeRes = 1; - } - else - { - var h2 = space.RadiansFromDegrees().Atan(); // fraction of data sample on half cube - var hres = (int)(1.0 / h2).Round(); - cubeRes = Fun.Min(2048, 4 * hres); // x2 sampling rate - } - - // TODO: use monochrome CreateCubeMapSide function of next Aardvark.Base version - var cubeFaces = new PixImage[6].SetByIndex(i => (PixImage)PixImage.CreateCubeMapSide(i, cubeRes, 4, v => new C4f(sampler.GetIntensity(v)))); - var cubeFaces1Ch = cubeFaces.Map(p => (PixImage)new PixImage(p.ToPixImage().GetChannel(0L).AsVolume())); - return new PixCube(cubeFaces1Ch); - } - } -} diff --git a/src/Aardvark.Data.Photometry/TextParser.cs b/src/Aardvark.Data.Photometry/TextParser.cs deleted file mode 100644 index cee5fa2c..00000000 --- a/src/Aardvark.Data.Photometry/TextParser.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -using System.Globalization; -using System.IO; - -namespace Aardvark.Data.Photometry -{ - class TextParser - { - protected double ReadDoubleLine(StreamReader s) - { - var temp = s.ReadLine().Trim(); - - if (String.IsNullOrEmpty(temp)) return 0.0f; - return ParseDouble(temp); - } - - protected int ReadIntLine(StreamReader s) - { - var temp = s.ReadLine().Trim(); - - if (String.IsNullOrEmpty(temp)) return 0; - return ParseInt(temp); - } - - protected static double ParseDouble(String s) - { - return Double.Parse(s, CultureInfo.InvariantCulture); - } - - protected static int ParseInt(String s) - { - return (int)Decimal.Parse(s); // NOTE use decimal parsing to not crash with floating point values (could report warning) - } - - protected String[] StringSplit(String s) - { - char[] splitChar = new char[] { ' ' }; - return s.Split(splitChar, StringSplitOptions.RemoveEmptyEntries); - } - - protected String[] LabelSplitForDict(String s) - { - String[] temp = s.Split(']'); - temp[0] = temp[0].Remove(0, 1).Trim(); - temp[1] = temp[1].Trim(); - - return temp; - } - } -} diff --git a/src/Aardvark.Data.Photometry/paket.references b/src/Aardvark.Data.Photometry/paket.references deleted file mode 100644 index e4fb028b..00000000 --- a/src/Aardvark.Data.Photometry/paket.references +++ /dev/null @@ -1,2 +0,0 @@ -Aardvark.Build -Aardvark.Base.IO \ No newline at end of file diff --git a/src/Aardvark.Data.Photometry/paket.template b/src/Aardvark.Data.Photometry/paket.template deleted file mode 100644 index ac0d107c..00000000 --- a/src/Aardvark.Data.Photometry/paket.template +++ /dev/null @@ -1,11 +0,0 @@ -type project -id Aardvark.Data.Photometry -authors Aardvark Platform Team -owners Aardvark Platform Team -projectUrl http://github.com/aardvark-platform -licenseUrl http://www.gnu.org/licenses/agpl.txt -repositoryType git -repositoryUrl https://github.com/aardvark-platform/aardvark.algodat -description - Aardvark.Data.Photometry -include-pdbs true \ No newline at end of file diff --git a/src/Aardvark.Data.Wavefront/Aardvark.Data.Wavefront.csproj b/src/Aardvark.Data.Wavefront/Aardvark.Data.Wavefront.csproj deleted file mode 100644 index 48487307..00000000 --- a/src/Aardvark.Data.Wavefront/Aardvark.Data.Wavefront.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - netstandard2.0 - - - ..\..\bin\Debug - ..\..\bin\Debug\netstandard2.0\Aardvark.Data.Wavefront.xml - 1701;1702;1705;1591 - - - ..\..\bin\Release - ..\..\bin\Release\netstandard2.0\Aardvark.Data.Wavefront.xml - 1701;1702;1705;1591 - - - - - - \ No newline at end of file diff --git a/src/Aardvark.Data.Wavefront/Exporter.cs b/src/Aardvark.Data.Wavefront/Exporter.cs deleted file mode 100644 index 25c561f3..00000000 --- a/src/Aardvark.Data.Wavefront/Exporter.cs +++ /dev/null @@ -1,465 +0,0 @@ -using Aardvark.Base; -using Aardvark.Geometry; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; - -namespace Aardvark.Data.Wavefront -{ - public static class Exporter - { - public class ObjCoderState : IDisposable - { - string m_filename; - string m_path; - int m_vertexCount; - int m_texCoordCount; - int m_normalCount; - int m_faceCount; - StreamWriter m_geometryStream; - StreamWriter m_materialStream; - - int m_geometryCount; - - public ObjCoderState(string fn) - { - m_filename = Path.GetFileNameWithoutExtension(fn); - m_path = Path.GetDirectoryName(fn); - - var objFn = Path.Combine(m_path, m_filename + ".obj"); - var matFn = Path.Combine(m_path, m_filename + ".mtl"); - - m_geometryStream = new StreamWriter(new FileStream(objFn, FileMode.Create)); - m_materialStream = new StreamWriter(new FileStream(matFn, FileMode.Create)); - - m_geometryStream.WriteLine("mtllib {0}.mtl", m_filename); - } - - static SymbolDict s_materialEntries = new SymbolDict() - { - { WavefrontMaterial.Property.AmbientColor, "Ka" }, - { WavefrontMaterial.Property.EmissiveColor, "Ke" }, - { WavefrontMaterial.Property.DiffuseColor, "Kd" }, - { WavefrontMaterial.Property.SpecularColor, "Ks" }, - { WavefrontMaterial.Property.SpecularExponent, "Ns" }, - { WavefrontMaterial.Property.TransmissionFilter, "Tf" }, - { WavefrontMaterial.Property.Opacity, "Tr" }, // or "d" with 1-Tr - { WavefrontMaterial.Property.IlluminationModel, "illum" }, - { WavefrontMaterial.Property.Sharpness, "sharpness" }, - { WavefrontMaterial.Property.OpticalDensity, "Ni" }, - - { WavefrontMaterial.Property.AmbientColorMap, "map_Ka" }, - { WavefrontMaterial.Property.DiffuseColorMap, "map_Kd" }, - { WavefrontMaterial.Property.SpecularColorMap, "map_Ks" }, - { WavefrontMaterial.Property.SpecularExponentMap, "map_Ns" }, - { WavefrontMaterial.Property.OpacityMap, "map_d" }, - { WavefrontMaterial.Property.DecalMap, "decal" }, - { WavefrontMaterial.Property.DisplacementMap, "disp" }, - { WavefrontMaterial.Property.BumpMap, "map_bump" }, // or "bump" - }; - - static Dictionary> s_valueFormatters = new Dictionary>() - { - { typeof(C3f), new Func(v => String.Format(CultureInfo.InvariantCulture, "{0} {1} {2}", ((C3f)v).R, ((C3f)v).G, ((C3f)v).B)) }, - { typeof(C3b), new Func(v => String.Format(CultureInfo.InvariantCulture, "{0} {1} {2}", ((C3b)v).R, ((C3b)v).G, ((C3b)v).B)) }, - { typeof(double), new Func(v => String.Format(CultureInfo.InvariantCulture, "{0}", v)) }, - { typeof(float), new Func(v => String.Format(CultureInfo.InvariantCulture, "{0}", v)) }, - { typeof(int), new Func(v => String.Format(CultureInfo.InvariantCulture, "{0}", v)) }, - { typeof(string), new Func(v => String.Format(CultureInfo.InvariantCulture, "{0}", v)) }, - }; - - public void AppendMaterial(WavefrontMaterial material) - { - m_materialStream.WriteLine("newmtl {0}", material.Name); - - material.MapItems.ForEach(e => - { - string entryName; - if (s_materialEntries.TryGetValue(e.Key, out entryName)) - { - string valueString = null; - Func formatter; - if (s_valueFormatters.TryGetValue(e.Value.GetType(), out formatter)) - valueString = formatter(e.Value); - else - Report.Warn("could not format entry {0} of type {1}", entryName, e.Value.GetType()); - //valueString = e.ToString(); // might produce corrupted file - - if (valueString != null) - m_materialStream.WriteLine("\t{0} {1}", entryName, valueString); - } - }); - - // append an empty line - m_materialStream.WriteLine(); - } - - //public void AppendGeometry(VertexGeometry vg, string groupName = null, string materialName = null) - //{ - // vg = vg.ToIndexedVertexGeometry(); - // var coords = vg.Positions as V3f[]; - // var normals = vg.Normals as V3f[]; - // var colors = vg.Colors as C4b[]; - // var texCoord = vg.DiffuseColorCoordinates() as V2f[]; - // var indices = vg.Indices as int[]; - // //var tex = vg.DiffuseColorTexture(); - - // if (texCoord == null) - // texCoord = new V2f[coords.Length]; - // if (normals == null) - // normals = new V3f[coords.Length]; - - // // write signatures of new geometry - // if (groupName != null) - // m_geometryStream.WriteLine("g {0}", groupName); - // if (materialName != null) - // m_geometryStream.WriteLine("usemtl {0}", materialName); - - // // write geometry - - // // (+1) for one base indices - // var baseVertexIndex = m_vertexCount + 1; - // var baseNormalIndex = m_normalCount + 1; - // var baseTexCoordIndex = m_texCoordCount + 1; - - // coords.ForEach(v => m_geometryStream.WriteLine(String.Format(CultureInfo.InvariantCulture, "v {0} {1} {2}", v.X, v.Y, v.Z))); - // m_vertexCount += coords.Length; - - // if (normals != null) - // { - // normals.ForEach(vn => m_geometryStream.WriteLine(String.Format(CultureInfo.InvariantCulture, "vn {0} {1} {2}", vn.X, vn.Y, vn.Z))); - // m_normalCount += normals.Length; - // } - // if (texCoord != null) - // { - // texCoord.ForEach(vt => m_geometryStream.WriteLine(String.Format(CultureInfo.InvariantCulture, "vt {0} {1}", vt.X, 1 - vt.Y))); - // m_texCoordCount += texCoord.Length; - // } - // //if (colors != null) // not supported - // // colors.Run(vc => m_geometryStream.WriteLine("vc {0} {1} {2} {3}", vc.R, vc.G, vc.B, vc.A)); - - // // base- vertex/tex/normal indices are the same - // for (int i = 0; i < vg.TriangleCount; i++) - // { - // var i0 = indices[i * 3 + 0]; - // var i1 = indices[i * 3 + 1]; - // var i2 = indices[i * 3 + 2]; - - // if (normals != null && texCoord != null) - // { - // m_geometryStream.WriteLine("f {0}/{1}/{2} {3}/{4}/{5} {6}/{7}/{8}", - // i0 + baseVertexIndex, i0 + baseNormalIndex, i0 + baseTexCoordIndex, - // i1 + baseVertexIndex, i1 + baseNormalIndex, i1 + baseTexCoordIndex, - // i2 + baseVertexIndex, i2 + baseNormalIndex, i2 + baseTexCoordIndex); - // } - // else - // { - // if (normals != null) - // m_geometryStream.WriteLine("f {0}/{1} {2}/{3} {4}/{5}", - // i0 + baseVertexIndex, i0 + baseNormalIndex, - // i1 + baseVertexIndex, i1 + baseNormalIndex, - // i2 + baseVertexIndex, i2 + baseNormalIndex); - // else if (texCoord != null) - // m_geometryStream.WriteLine("f {0}//{1} {2}//{3} {4}//{5}", - // i0 + baseVertexIndex, i0 + baseTexCoordIndex, - // i1 + baseVertexIndex, i1 + baseTexCoordIndex, - // i2 + baseVertexIndex, i2 + baseTexCoordIndex); - // else - // m_geometryStream.WriteLine("f {0} {1} {2}", i0 + baseVertexIndex, i1 + baseVertexIndex, i2 + baseVertexIndex); - // } - // } - - // m_faceCount += vg.TriangleCount; - - // m_geometryCount++; - //} - - //public void AppendGeometry(ConcreteVertexGeometry cvg) - //{ - // var vg = cvg.TransformedVertexGeometry; - // var material = cvg.Surface as Instance; - // var materialName = string.Format("material{0}", m_geometryCount); - // AppendGeometry(vg, material, materialName); - //} - - //public void AppendGeometry(VertexGeometry vg, Instance material, string groupName) - //{ - // vg = vg.ToIndexedVertexGeometry(); - // var coords = vg.Positions as V3f[]; - // var normals = vg.Normals as V3f[]; - // var colors = vg.Colors as C4b[]; - // var texCoord = vg.DiffuseColorCoordinates() as V2f[]; - // var indices = vg.Indices as int[]; - // //var tex = vg.DiffuseColorTexture(); - - // if (texCoord == null) - // texCoord = new V2f[coords.Length]; - // if (normals == null) - // normals = new V3f[coords.Length]; - - // // write material - // m_materialStream.WriteLine("newmtl {0}", groupName); - - // C3f diffuse = C3f.Gray80; - // C3f ambient = C3f.Gray20; - // C3f specular = C3f.Black; - // float opacity = 1; - // float shinyness = 0; - - - // if (material != null) - // { - // //object temp; - // //if (material.TryGetValue(SgOld.DefaultSurface.Property.DiffuseColor, out temp) && temp is C4f) - // //{ - // // diffuse = ((C4f)temp).ToC3f(); - // // opacity = ((C4f)temp).A; - // //} - - // //if (material.TryGetValue(SgOld.DefaultSurface.Property.AmbientColor, out temp) && temp is C4f) - // // ambient = ((C4f)temp).ToC3f(); - - // //if (material.TryGetValue(SgOld.DefaultSurface.Property.SpecularColor, out temp) && temp is C4f) - // // specular = ((C4f)temp).ToC3f(); - - // //if (material.TryGetValue(SgOld.DefaultSurface.Property.Shininess, out temp) && temp is double) - // // shinyness = (float)((double)temp); - // } - - // if (colors != null) - // { - // var vertexColor = colors[0].ToC4f(); - // diffuse = (C3f)(diffuse.ToV3f() * vertexColor.ToV3f()); - // opacity *= vertexColor.A; - // } - - // m_materialStream.WriteLine(String.Format(CultureInfo.InvariantCulture, "Ka {0} {1} {2}", ambient.R, ambient.G, ambient.B)); - // m_materialStream.WriteLine(String.Format(CultureInfo.InvariantCulture, "Kd {0} {1} {2}", diffuse.R, diffuse.G, diffuse.B)); - - // //if (tex != null) - // //{ - // // var texFilename = string.Format("vgtexture{0}.png", m_geometryCount); - // // m_materialStream.WriteLine("map_Kd {0}", texFilename); - - // // var convertible = PixImageSetConvertible.Create(); - // // tex.Convertible.ConvertInto(convertible); - // // convertible.PixImagesFromConvertible().First().SaveAsImage(Path.Combine(m_path, texFilename)); - // // //tex.Convertible.ConvertInto(BitmapConvertible.CreateFile(Path.Combine(m_path, texFilename))); - // //} - - // var illum = 1; - - // if (specular != C3f.Black && shinyness != 0) - // { - // illum = 2; - // m_materialStream.WriteLine(String.Format(CultureInfo.InvariantCulture, "Ks {0} {1} {2}", specular.R, specular.G, specular.B)); - // m_materialStream.WriteLine(String.Format(CultureInfo.InvariantCulture, "Ns {0}", shinyness)); - // } - // else - // { - // m_materialStream.WriteLine(String.Format(CultureInfo.InvariantCulture, "Ns {0}", 0)); - // } - - // if (opacity != 1) - // { - // illum = 9; // glass - // m_materialStream.WriteLine(String.Format(CultureInfo.InvariantCulture, "Tf {0} {1} {2}", opacity, opacity, opacity)); - // } - - // m_materialStream.WriteLine("illum {0}", illum); - - // // write geometry - - // // (+1) for one base indices - // var baseVertexIndex = m_vertexCount + 1; - // var baseNormalIndex = m_normalCount + 1; - // var baseTexCoordIndex = m_texCoordCount + 1; - - // coords.ForEach(v => m_geometryStream.WriteLine(String.Format(CultureInfo.InvariantCulture, "v {0} {1} {2}", v.X, v.Y, v.Z))); - // m_vertexCount += coords.Length; - - // if (normals != null) - // { - // normals.ForEach(vn => m_geometryStream.WriteLine(String.Format(CultureInfo.InvariantCulture, "vn {0} {1} {2}", vn.X, vn.Y, vn.Z))); - // m_normalCount += normals.Length; - // } - // if (texCoord != null) - // { - // texCoord.ForEach(vt => m_geometryStream.WriteLine(String.Format(CultureInfo.InvariantCulture, "vt {0} {1}", vt.X, 1 - vt.Y))); - // m_texCoordCount += texCoord.Length; - // } - // //if (colors != null) // not supported - // // colors.Run(vc => m_geometryStream.WriteLine("vc {0} {1} {2} {3}", vc.R, vc.G, vc.B, vc.A)); - - // m_geometryStream.WriteLine("g {0}", groupName); - // m_geometryStream.WriteLine("usemtl {0}", groupName); - - // // base- vertex/tex/normal indices are the same - // for (int i = 0; i < vg.TriangleCount; i++) - // { - // var i0 = indices[i * 3 + 0]; - // var i1 = indices[i * 3 + 1]; - // var i2 = indices[i * 3 + 2]; - - // if (normals != null && texCoord != null) - // { - // m_geometryStream.WriteLine("f {0}/{1}/{2} {3}/{4}/{5} {6}/{7}/{8}", - // i0 + baseVertexIndex, i0 + baseNormalIndex, i0 + baseTexCoordIndex, - // i1 + baseVertexIndex, i1 + baseNormalIndex, i1 + baseTexCoordIndex, - // i2 + baseVertexIndex, i2 + baseNormalIndex, i2 + baseTexCoordIndex); - // } - // else - // { - // if (normals != null) - // m_geometryStream.WriteLine("f {0}/{1} {2}/{3} {4}/{5}", - // i0 + baseVertexIndex, i0 + baseNormalIndex, - // i1 + baseVertexIndex, i1 + baseNormalIndex, - // i2 + baseVertexIndex, i2 + baseNormalIndex); - // else if (texCoord != null) - // m_geometryStream.WriteLine("f {0}//{1} {2}//{3} {4}//{5}", - // i0 + baseVertexIndex, i0 + baseTexCoordIndex, - // i1 + baseVertexIndex, i1 + baseTexCoordIndex, - // i2 + baseVertexIndex, i2 + baseTexCoordIndex); - // else - // m_geometryStream.WriteLine("f {0} {1} {2}", i0 + baseVertexIndex, i1 + baseVertexIndex, i2 + baseVertexIndex); - // } - // } - - // m_faceCount += vg.TriangleCount; - - // m_geometryCount++; - //} - - private static WavefrontMaterial s_defaultMaterial; - private static WavefrontMaterial GetDefaultMaterial() - { - if (s_defaultMaterial == null) - { - s_defaultMaterial = new WavefrontMaterial("default"); - - s_defaultMaterial[WavefrontMaterial.Property.DiffuseColor] = C3f.Gray80; - s_defaultMaterial[WavefrontMaterial.Property.AmbientColor] = C3f.Gray20; - s_defaultMaterial[WavefrontMaterial.Property.IlluminationModel] = 1; - } - - return s_defaultMaterial; - } - - /// - /// Appends the supplied geometry to the Wavefront Obj. - /// Normals/DiffuseColorCoordinates will be only exported when supplied as non-indexed VertexAttributes. - /// - /// Mesh - /// Optional group name (g) - /// Optional material name (usemtl) / otherwise a default material will be created/used - public void AppendGeometry(PolyMesh mesh, string groupName = null, string materialName = null) - { - var coords = mesh.Vertices.Select(p => (V3f)p.Position).ToArray(); - - V3f[] normals = null; - V2f[] texCoords = null; - - if (mesh.VertexAttributes.Contains(PolyMesh.Property.Normals)) - normals = mesh.VertexAttributeArray(PolyMesh.Property.Normals).Select(V3f.FromV3d).TakeToArray(coords.Length); - if (mesh.VertexAttributes.Contains(PolyMesh.Property.DiffuseColorCoordinates)) - texCoords = mesh.VertexAttributeArray(PolyMesh.Property.DiffuseColorCoordinates).Select(V2f.FromV2d).TakeToArray(coords.Length); - - // write signatures of new geometry - if (groupName != null) - m_geometryStream.WriteLine("g {0}", groupName); - if (materialName == null) - { - var mat = GetDefaultMaterial(); - materialName = mat.Name; - AppendMaterial(mat); - } - m_geometryStream.WriteLine("usemtl {0}", materialName); - - // (+1) for one base indices - var baseVertexIndex = m_vertexCount + 1; - var baseNormalIndex = m_normalCount + 1; - var baseTexCoordIndex = m_texCoordCount + 1; - - // write geometry - coords.ForEach(v => m_geometryStream.WriteLine(String.Format(CultureInfo.InvariantCulture, "v {0} {1} {2}", v.X, v.Y, v.Z))); - m_vertexCount += coords.Length; - - if (normals != null) - { - normals.ForEach(vn => m_geometryStream.WriteLine(String.Format(CultureInfo.InvariantCulture, "vn {0} {1} {2}", vn.X, vn.Y, vn.Z))); - m_normalCount += normals.Length; - } - if (texCoords != null) - { - texCoords.ForEach(vt => m_geometryStream.WriteLine(String.Format(CultureInfo.InvariantCulture, "vt {0} {1}", vt.X, 1 - vt.Y))); - m_texCoordCount += texCoords.Length; - } - - // base- vertex/tex/normal indices are the same - for (int i = 0; i < mesh.FaceCount; i++) - { - var face = mesh.GetFace(i); - string faceString = ""; - if (normals == null && texCoords == null) - faceString = "f " + face.VertexIndices.Select(idx => - (baseVertexIndex + idx).ToString()).Join(" "); - else if (normals == null) - faceString = "f " + face.VertexIndices.Select(idx => - (baseVertexIndex + idx).ToString() + "//" + - (baseTexCoordIndex + idx).ToString()).Join(" "); - else if (texCoords == null) - faceString = "f " + face.VertexIndices.Select(idx => - (baseVertexIndex + idx).ToString() + "/" + - (baseNormalIndex + idx).ToString()).Join(" "); - else - faceString = "f " + face.VertexIndices.Select(idx => - (baseVertexIndex + idx).ToString() + "/" + - (baseNormalIndex + idx).ToString() + "/" + - (baseTexCoordIndex + idx).ToString()).Join(" "); - - m_geometryStream.WriteLine(faceString); - } - - m_faceCount += mesh.FaceCount; - - m_geometryCount++; - } - - - #region IDisposable Members - - public void Dispose() - { - m_geometryStream.Close(); - m_materialStream.Close(); - } - - #endregion - }; - - //public static void SaveToFile(IEnumerable vgs, string fn) - //{ - // var state = new ObjCoderState(fn); - - // vgs.ForEach(vg => state.AppendGeometry(vg)); - - // state.Dispose(); - //} - - /// - /// Exports a sequence of PolyMeshes to the given file. - /// A default material will be used for all geometries. - /// Normals/DiffuseColorCoordinates will be only exported when supplied as non-indexed VertexAttributes. - /// - public static void SaveToFile(IEnumerable polyMeshes, string fn) - { - var state = new ObjCoderState(fn); - - polyMeshes.ForEach(pm => state.AppendGeometry(pm)); - - state.Dispose(); - } - } -} diff --git a/src/Aardvark.Data.Wavefront/LICENSE b/src/Aardvark.Data.Wavefront/LICENSE deleted file mode 100644 index 6a40b899..00000000 --- a/src/Aardvark.Data.Wavefront/LICENSE +++ /dev/null @@ -1,203 +0,0 @@ -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Aardvark Platform - Copyright (C) 2006-2019 Aardvark Platform Team - https://aardvark.graphics - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/src/Aardvark.Data.Wavefront/MtlParser.cs b/src/Aardvark.Data.Wavefront/MtlParser.cs deleted file mode 100644 index 82507aae..00000000 --- a/src/Aardvark.Data.Wavefront/MtlParser.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Aardvark.Base; -using System.IO; -using System.Text; - -namespace Aardvark.Data.Wavefront -{ - public static class MtlParser - { - class ParseState : StreamParser - { - public List MaterialList = new List(); - - WavefrontMaterial m_currentMaterial; - - public ParseState(Stream stream, string baseDir = null) - : this(stream, Encoding.Default, baseDir) - { - } - - public ParseState(Stream stream, Encoding encoding, string baseDir = null) - : base(stream, encoding, baseDir) - { - } - - public void NewMaterial(IList args) - { - if (args.Count < 1) throw new ArgumentException("Invalid number of arguments"); - var name = args[0].ToString(); - m_currentMaterial = new WavefrontMaterial(name); - m_currentMaterial[WavefrontMaterial.Property.Path] = BaseDir; - MaterialList.Add(m_currentMaterial); - } - - public void SetAttribute(Symbol name, object value) - { - m_currentMaterial[name] = value; - } - } - - /// - /// Parses a mtl file into wavefront materials. - /// The encoding is assumed based on the platform. - /// Throws an exception if the file is not found. - /// - public static List Load(string fileName) - { - return Load(fileName, Encoding.Default); - } - - /// - /// Parses a mtl file into wavefront materials. - /// Throws an exception if the file is not found. - /// - public static List Load(string fileName, Encoding encoding) - { - if (!File.Exists(fileName)) - throw new FileNotFoundException("Material library file \"{0}\" not found", fileName); - - var stream = File.OpenRead(fileName); - return Load(stream, Encoding.Default, Path.GetDirectoryName(fileName)); - } - - /// - /// Parses a mtl file contained in a stream into wavefront materials. - /// The encoding is assumed based on the platform. - /// The baseDir argument is optional and can be used to store texture file names using absolute paths. - /// - public static List Load(Stream stream, string baseDir = null) - { - return Load(stream, Encoding.Default, baseDir); - } - - /// - /// Parses a mtl file contained in a stream into wavefront materials. - /// The baseDir argument is optional and can be used to store texture file names using absolute paths. - /// - public static List Load(Stream stream, Encoding encoding, string baseDir = null) - { - var parseState = new ParseState(stream, encoding, baseDir); - WavefrontParser.Parse(parseState, s_attributeParsers); - return parseState.MaterialList; - } - - static Dictionary>> s_attributeParsers = - new Dictionary>> - { - { new Text("Ka"), (s, a) => s.SetAttribute(WavefrontMaterial.Property.AmbientColor, Primitives.ParseColor(a)) }, - { new Text("Kd"), (s, a) => s.SetAttribute(WavefrontMaterial.Property.DiffuseColor, Primitives.ParseColor(a))}, - { new Text("Ke"), (s, a) => s.SetAttribute(WavefrontMaterial.Property.EmissiveColor, Primitives.ParseColor(a)) }, - { new Text("Ks"), (s, a) => s.SetAttribute(WavefrontMaterial.Property.SpecularColor, Primitives.ParseColor(a)) }, - { new Text("Ns"), (s, a) => s.SetAttribute(WavefrontMaterial.Property.SpecularExponent, Primitives.ParseFloat(a)) }, - { new Text("Tf"), (s, a) => s.SetAttribute(WavefrontMaterial.Property.TransmissionFilter, Primitives.ParseColor(a)) }, - { new Text("Tr"), (s, a) => s.SetAttribute(WavefrontMaterial.Property.Opacity, 1 - Primitives.ParseFloat(a)) }, - { new Text("d"), (s, a) => s.SetAttribute(WavefrontMaterial.Property.Opacity, Primitives.ParseFloat(a)) }, - { new Text("illum"),(s, a) => s.SetAttribute(WavefrontMaterial.Property.IlluminationModel, Primitives.ParseInt(a)) }, - { new Text("sharpness"),(s, a) => s.SetAttribute(WavefrontMaterial.Property.Sharpness, Primitives.ParseInt(a)) }, - { new Text("Ni"), (s, a) => s.SetAttribute(WavefrontMaterial.Property.OpticalDensity, Primitives.ParseFloat(a)) }, - - { new Text("map_Ka"), (s, a) => s.SetAttribute(WavefrontMaterial.Property.AmbientColorMap, Primitives.ParseMap(a, s.BaseDir)) }, - { new Text("map_Kd"), (s, a) => s.SetAttribute(WavefrontMaterial.Property.DiffuseColorMap, Primitives.ParseMap(a, s.BaseDir)) }, - { new Text("map_Ks"), (s, a) => s.SetAttribute(WavefrontMaterial.Property.SpecularColorMap, Primitives.ParseMap(a, s.BaseDir)) }, - { new Text("map_Kn"), (s, a) => s.SetAttribute(WavefrontMaterial.Property.NormalMap, Primitives.ParseMap(a, s.BaseDir)) }, - { new Text("map_Ke"), (s, a) => s.SetAttribute(WavefrontMaterial.Property.EmissiveColorMap, Primitives.ParseMap(a, s.BaseDir)) }, - { new Text("map_Ns"), (s, a) => s.SetAttribute(WavefrontMaterial.Property.SpecularExponentMap, Primitives.ParseMap(a, s.BaseDir)) }, - { new Text("map_d"), (s, a) => s.SetAttribute(WavefrontMaterial.Property.OpacityMap, Primitives.ParseMap(a, s.BaseDir)) }, - { new Text("decal"), (s, a) => s.SetAttribute(WavefrontMaterial.Property.DecalMap, Primitives.ParseMap(a, s.BaseDir)) }, - { new Text("disp"), (s, a) => s.SetAttribute(WavefrontMaterial.Property.DisplacementMap, Primitives.ParseMap(a, s.BaseDir)) }, - { new Text("map_bump"), (s, a) => s.SetAttribute(WavefrontMaterial.Property.BumpMap, Primitives.ParseMap(a, s.BaseDir)) }, - { new Text("bump"), (s, a) => s.SetAttribute(WavefrontMaterial.Property.BumpMap, Primitives.ParseMap(a, s.BaseDir)) }, - - // refl ... todo -type - - { new Text("newmtl"), (s, a) => s.NewMaterial(a) } - }; - } -} diff --git a/src/Aardvark.Data.Wavefront/ObjParser.cs b/src/Aardvark.Data.Wavefront/ObjParser.cs deleted file mode 100644 index 9fb66a08..00000000 --- a/src/Aardvark.Data.Wavefront/ObjParser.cs +++ /dev/null @@ -1,494 +0,0 @@ -using Aardvark.Base; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; - -namespace Aardvark.Data.Wavefront -{ - class StreamParser - { - StreamReader m_reader; - - /// - /// Returns the initial encoding the StreamReader has been created with. - /// - public Encoding Encoding { get; } - - public string BaseDir { get; } - - public Text Line { get; private set; } - - public bool EndOfText { get; private set; } - - /// - /// Move to the next line of the Stream. - /// Lines ending with '\' are joined. - /// Returns false if the end of the stream has been reached. - /// - public bool NextLine() - { - if (m_reader.EndOfStream) - { - EndOfText = true; - Line = Text.Empty; - return false; - } - - // lines are allowed to be joined when ended with line continuation character (\) - var line = String.Empty; - var str = String.Empty; - do - { - str = m_reader.ReadLine().TrimEnd(); - line = line + str; - //var test = str.Length > 0 && str[str.Length - 1] == '\\'; - //if (test) Report.Line("JOIN"); - } - while (str.Length > 0 && str[str.Length - 1] == '\\'); - - Line = new Text(line); - return true; - } - - /// - /// NOTE: if byte order marks are present the specified encoding will be overruled - /// - public StreamParser(Stream stream, Encoding encoding, string baseDir = null) - { - Encoding = encoding; - m_reader = new StreamReader(stream, encoding, true); - EndOfText = m_reader.EndOfStream; - Line = Text.Empty; - BaseDir = baseDir; - } - } - - public static class ObjParser - { - internal class ParseState : StreamParser - { - public WavefrontObject Object = new WavefrontObject(); - - int m_currentMaterial = -1; - int m_currentGroup = -1; - int m_currentSmoothGroup = -1; - - - Dictionary m_mtlLib = new Dictionary(); - Dictionary m_mtlIndices = new Dictionary(); - - Dictionary m_groups = new Dictionary(); - - public ParseState(Stream stream, Encoding encoding, string baseDir = null) - : base(stream, encoding, baseDir) - { - } - - public ParseState(Stream stream, Encoding encoding, string baseDir = null, bool useDoublePrecision = false) - : base(stream, encoding, baseDir) - { - Object = new WavefrontObject(useDoublePrecision); - } - - - static bool multipleGroupsWarningShown = false; - - public void SetGroup(IEnumerable args) - { - var name = args.First(); - if (name.IsEmpty) throw new InvalidOperationException(); - - if (!m_groups.TryGetValue(name, out m_currentGroup)) - { - var gl = Object.Groups; - m_currentGroup = gl.Count; - m_groups[name] = gl.Count; - gl.Add(name.ToString()); - } - - if ((args.Count() > 1) && (!multipleGroupsWarningShown)) - { - Report.Warn("multiple groups are ignored"); - multipleGroupsWarningShown = true; - } - } - - public void SetMaterial(IEnumerable args) - { - var name = args.Single(); - if (name.IsEmpty) throw new InvalidOperationException(); - - if (m_mtlLib.TryGetValue(name, out WavefrontMaterial mtl)) - { - if (!m_mtlIndices.TryGetValue(mtl, out m_currentMaterial)) - { - var ml = Object.Materials; - m_currentMaterial = ml.Count; - m_mtlIndices[mtl] = ml.Count; - ml.Add(mtl); - } - } - else - { -#if DEBUG - Report.Warn("could not find material: {0}", name); -#endif - m_currentMaterial = -1; - } - } - - public void SetSmoothingGroup(IEnumerable args) - { - var sg = args.Single(); - - m_currentSmoothGroup = sg == "off" ? -1 : sg.ParseIntValue(); - } - - bool TryLoadMaterialLib(string fileName, Encoding encoding) - { - try - { - if (!string.IsNullOrEmpty(BaseDir)) - fileName = Path.Combine(BaseDir, fileName); - - var materials = MtlParser.Load(fileName, encoding); - m_mtlLib.AddRange(materials.Select(m => KeyValuePairs.Create(new Text(m.Name), m))); - return true; - } - catch (Exception e) - { - Report.Line("error loading material library: " + e.Message); - } - return false; - } - - internal void LoadMaterialLibs(IEnumerable args, Encoding encoding) - { - if (args.IsEmpty()) return; - - // white spaces within filename possible (although not explicitly in specification) -> try interpretation of all texts as one - - var first = args.First(); - var start = first.Start; - var end = args.Last().End; - var fileName = first.String.Substring(start, end - start); - - if (TryLoadMaterialLib(fileName, encoding)) // if successfully loaded mtl lib with merged filename -> return - return; - - foreach (var file in args) - TryLoadMaterialLib(file.ToString(), encoding); - } - - public void AddPointSet(IList indices) - { - var indexCount = indices.Count; - if (indexCount < 1) throw new InvalidOperationException("Point vertex index missing"); - - var ps = Object.PointsSets.LastOrDefault(); - if (ps == null || ps.GroupIndex != this.m_currentGroup) - { - ps = new WavefrontObject.PointSet(); - ps.GroupIndex = this.m_currentGroup; - Object.PointsSets.Add(ps); - } - - var vertexCount = Object.Vertices.Count; - - foreach (var i in indices) - { - var index = i.ParseIntValue(); - if (index == 0) throw new InvalidOperationException("Invalid point vertex index"); - ps.VertexIndices.Add(index > 0 ? index - 1 : vertexCount - index); - } - - var mi = this.m_currentMaterial; - ps.MaterialIndices.Add(mi); - ps.FirstIndices.Add(ps.VertexIndices.Count); - } - - public void AddLineStrip(IList indices) - { - var indexCount = indices.Count; - if (indexCount < 2) throw new InvalidOperationException("LineStrip must have at least to indices"); - - var ls = Object.LineSets.LastOrDefault(); - if (ls == null || ls.GroupIndex != this.m_currentGroup) - { - ls = new WavefrontObject.LineSet(); - ls.GroupIndex = this.m_currentGroup; - Object.LineSets.Add(ls); - } - - var vertexCount = Object.Vertices.Count; - var coordCount = Object.TextureCoordinates.Count; - - ls.VertexCountRange.EnlargeBy(indices.Count); - - int indexAttributeLayout = -1; - foreach (var i in indices) - { - // l vi vi vi ... - // l vi/ti vi/ti vi/ti ... - - // indices can be supplied by absolute vertex index or relative using negative numbers - // absolute vertex indices start by 1, index value 0 indicates not specified attribute - - var ai = i.Split('/').GetEnumerator(); - var iaLayout = 0; - - var vi = 0; - if (ai.MoveNext() && ai.Current.Count > 0) - { - iaLayout |= 0x01; - vi = ai.Current.ParseIntValue(); - } - else - throw new InvalidOperationException("Missing vertex index element"); - - var ti = 0; - if (ai.MoveNext() && ai.Current.Count > 0) - { - ti = ai.Current.ParseIntValue(); - iaLayout |= 0x02; - } - - if (ai.MoveNext()) - throw new InvalidOperationException("Invalid index element count"); - - if (indexAttributeLayout == -1) - indexAttributeLayout = iaLayout; - else if (iaLayout != indexAttributeLayout) - throw new InvalidOperationException("Different index element counts"); - - // indices can be supplied by absolute vertex index or relative using negative numbers - ls.VertexIndices.Add(vi > 0 ? vi - 1 : vertexCount + vi); - ls.TexCoordIndices.Add(ti > 0 ? ti - 1 : ti < 0 ? coordCount + ti : -1); - } - - var mi = this.m_currentMaterial; - ls.MaterialIndices.Add(mi); - ls.FirstIndices.Add(ls.VertexIndices.Count); - } - - public void AddFace(IList indices) - { - var indexCount = indices.Count; - if (indexCount < 3) throw new InvalidOperationException("Face must have at least 3 indices"); - - var fs = Object.FaceSets.LastOrDefault(); - if (fs == null || fs.GroupIndex != this.m_currentGroup) - { - fs = new WavefrontObject.FaceSet(); - fs.GroupIndex = this.m_currentGroup; - Object.FaceSets.Add(fs); - } - - var vertexCount = Object.Vertices.Count; - var coordCount = Object.TextureCoordinates.Count; - var normalCount = Object.Normals.Count; - - int indexAttributeLayout = -1; // make sure all vertex declarations are equal - - fs.FaceVertexCountRange.ExtendBy(indices.Count); - - foreach (var i in indices) - { - // f vi vi vi ... - // f vi/ti vi/ti vi/ti ... - // f vi//ni vi//ni vi//ni ... - // f vi/ti/ni vi/ti/ni vi/ti/ni ... - - // indices can be supplied by absolute vertex index or relative using negative numbers - // absolute vertex indices start by 1, index value 0 indicates not specified attribute - - var ai = i.Split('/').GetEnumerator(); - var iaLayout = 0; - - var vi = 0; - if (ai.MoveNext() && ai.Current.Count > 0) - { - iaLayout |= 0x01; - vi = ai.Current.ParseIntValue(); - } - else - throw new InvalidOperationException("Missing vertex index element"); - - var ti = 0; - if (ai.MoveNext() && ai.Current.Count > 0) - { - ti = ai.Current.ParseIntValue(); - iaLayout |= 0x02; - } - - var ni = 0; - if (ai.MoveNext() && ai.Current.Count > 0) - { - ni = ai.Current.ParseIntValue(); - iaLayout |= 0x04; - } - - if (ai.MoveNext()) - throw new InvalidOperationException("Invalid index element count"); - - if (indexAttributeLayout == -1) - indexAttributeLayout = iaLayout; - else if (iaLayout != indexAttributeLayout) - throw new InvalidOperationException("Different index element counts"); - - // handle absolute or relative indices - // TODO: keep track if all attributes have the same layout + keep track if any attribute is not used at all - // -> more efficient genernation of PolyMesh/IndexGeometry output that can exclude non-existing attributes (at the moment this is only done globally) - //var attributeIndexMask = (ti > 0 ? 0x1 : 0) | (ni > 0 ? 0x2 : 0); - vi = vi > 0 ? vi - 1 : vertexCount + vi; - ti = ti > 0 ? ti - 1 : ti < 0 ? coordCount + ti : -1; - ni = ni > 0 ? ni - 1 : ni < 0 ? normalCount + ni : -1; - fs.VertexIndices.Add(vi); - fs.TexCoordIndices.Add(ti); - fs.NormalIndices.Add(ni); - } - - var mi = this.m_currentMaterial; - fs.MaterialIndices.Add(mi); - fs.FirstIndices.Add(fs.VertexIndices.Count); - } - - internal void AddVertex(IList a) - { - // vertex (x, y, z, w) w == optional otherwise 1 - // extension for colors: (x, y, z, [w]) [(r, g, b)] - - if (a.Count < 3 || a.Count == 5 || a.Count > 7) throw new InvalidOperationException("Invalid number of index elements"); - - var va = Object.Vertices; - - if (Object.DoublePrecisionVertices) - { - ((List)va).Add(new V4d(a[0].ParseDoubleValue(), - a[1].ParseDoubleValue(), - a[2].ParseDoubleValue(), - a.Count == 4 || a.Count == 7 ? a[3].ParseDoubleValue() : 1)); - } - else - { - ((List)va).Add(new V4f(a[0].ParseFloatValue(), - a[1].ParseFloatValue(), - a[2].ParseFloatValue(), - a.Count == 4 || a.Count == 7 ? a[3].ParseFloatValue() : 1)); - } - - // get optional color data array (not initialized by default) - var ca = Object.VertexColors; - // fill up colors if the data array is create or there are colors - if (ca != null || a.Count > 4) - { - var c = C3f.White; - if (a.Count > 4) - { - var ci0 = a.Count == 7 ? 4 : 3; - c = new C3f(a[ci0].ParseFloatValue(), - a[ci0 + 1].ParseFloatValue(), - a[ci0 + 1].ParseFloatValue()); - } - // initialized vertex color array for all already read vertices in case not all vertices have colors - if (ca == null) - { - ca = new List(va.Count); - ca.AddRange(C3f.White, va.Count - 1); - Object.VertexColors = ca; - } - ca.Add(c); - } - } - } - - /// - /// Loads an obj from file. - /// The encoding is assumed based on the platform. - /// Throws an exception if the file cannot be found or read. - /// A mtllib will tried to be loaded from the same directory. - /// - public static WavefrontObject Load(string fileName) - { - return Load(fileName, Encoding.Default); - } - - /// - /// Loads an obj from file. - /// The encoding is assumed based on the platform. - /// Can be set to double or default float precision - /// Throws an exception if the file cannot be found or read. - /// A mtllib will tried to be loaded from the same directory. - /// - public static WavefrontObject Load(string fileName, bool useDoublePrecision = true) - { - return Load(fileName, Encoding.Default, useDoublePrecision); - } - - /// - /// Loads an obj from file. - /// Throws an exception if the file cannot be found or read. - /// A mtllib will tried to be loaded from the same directory. - /// - public static WavefrontObject Load(string fileName, Encoding encoding, bool useDoublePrecision = true) - { - var parseState = new ParseState(File.OpenRead(fileName), encoding, Path.GetDirectoryName(fileName), useDoublePrecision); - WavefrontParser.Parse(parseState, s_elementProcessors); - return parseState.Object; - } - - static Dictionary>> s_elementProcessors = - new Dictionary>>() - { - // Vertex data - { new Text(WavefrontObject.Property.Vertices.ToString()), (s, a) => s.AddVertex(a) }, - { new Text(WavefrontObject.Property.TextureCoordinates.ToString()), (s, a) => s.Object.TextureCoordinates.Add(Primitives.ParseTexCoord(a)) }, // tex coord (u, v, w) v, w == optinal - { new Text(WavefrontObject.Property.Normals.ToString()), (s, a) => s.Object.Normals.Add(Primitives.ParseVector(a)) }, // normal - { new Text(WavefrontObject.Property.ControlPoints.ToString()), (s, a) => s.Object.ControlPoints.Add(Primitives.ParseVector(a)) }, // point (u, v, w) - // cstype - // deg - // bmat - // step - - // Elements - { new Text(WavefrontObject.Property.PointSets.ToString()), (s, a) => s.AddPointSet(a) }, // p: point set - { new Text(WavefrontObject.Property.LineSets.ToString()), (s, a) => s.AddLineStrip(a) }, // l: line strip - { new Text(WavefrontObject.Property.FaceSets.ToString()), (s, a) => s.AddFace(a) }, // f: face - // curv - // curv2 - // surf - - // Free-form - // parm - // trim - // hole - // scrv - // sp - // end - - // Connectivity - // con - - // Grouping - { new Text(WavefrontObject.Property.Groups.ToString()), (s, a) => s.SetGroup(a) }, // group: name (name2, ...) NOTE: multi group not supported - { new Text("s"), (s, a) => s.SetSmoothingGroup(a) }, // smoothing group: "off"/-1 or index - // mg - // o - - // Render attributes - { new Text("mtllib"), (s, a) => s.LoadMaterialLibs(a, s.Encoding) }, // material library - { new Text(WavefrontObject.Property.Materials.ToString()), (s, a) => s.SetMaterial(a) }, // material - // bevel - // c_interp - // d_interp - // lod - // shadow_obj - // ctech - // stech - - //{ new Text("#"), (s, a) => { } }, // comment - }; - } -} diff --git a/src/Aardvark.Data.Wavefront/Primitives.cs b/src/Aardvark.Data.Wavefront/Primitives.cs deleted file mode 100644 index 801e791e..00000000 --- a/src/Aardvark.Data.Wavefront/Primitives.cs +++ /dev/null @@ -1,115 +0,0 @@ -using Aardvark.Base; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Runtime.CompilerServices; - -namespace Aardvark.Data.Wavefront -{ - public static class Primitives - { - public static C3f ParseColor(IList x) - { - if (x.Count < 3) throw new InvalidOperationException(); - return new C3f(x[0].ParseFloatValue(), - x[1].ParseFloatValue(), - x[2].ParseFloatValue()); - } - - public static V3f ParseTexCoord(IList x) - { - if (x.Count < 1) throw new InvalidOperationException(); - return new V3f(x[0].ParseFloatValue(), - x.Count > 1 ? 1 - x[1].ParseFloatValue() : 0, // temporary hack for sponza.obj - x.Count > 2 ? x[2].ParseFloatValue() : 0); - } - - public static V3f ParseVector(IList x) - { - if (x.Count < 3) throw new InvalidOperationException(); - return new V3f(x[0].ParseFloatValue(), - x[1].ParseFloatValue(), - x[2].ParseFloatValue()); - } - - public static V4f ParseVertex(IList x) - { - if (x.Count < 3) throw new InvalidOperationException(); - return new V4f(x[0].ParseFloatValue(), - x[1].ParseFloatValue(), - x[2].ParseFloatValue(), - x.Count > 3 ? x[3].ParseFloatValue() : 1); - } - - public static float ParseFloat(IList x) - { - if (x.Count < 1) throw new InvalidOperationException(); - return x[0].ParseFloatValue(); - } - - public static float ParseInt(IList x) - { - if (x.Count < 1) throw new InvalidOperationException(); - return x[0].ParseIntValue(); - } - - public static string ParseMap(IList x, string baseDir = null) - { - if (x.Count == 0) - return null; - // if (x.Count < 1) throw new InvalidOperationException(); - // Options: - - //-bm mult - //-blendu on | off - //-blendv on | off - //-cc on | off - //-clamp on | off - //-imfchan r | g | b | m | l | z - //-mm base gain - //-o u v w - //-s u v w - //-t u v w - //-texres value - - var fileName = x.Last().ToString(); - - if (!string.IsNullOrEmpty(baseDir)) - fileName = Path.Combine(baseDir, fileName); - - return fileName; // skip options and just take texture filename - } - - /// - /// Parses an integer from a Text that is already trimed of whitespace - /// NOTE: Use Text.ParsedValueOfIntAt(0) that contains an own parsing implementation - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int ParseIntValue(this Text t) - { - return t.ParsedValueOfIntAt(0).Value; - } - - /// - /// Parses a floating point value from a Text that is already trimed of whitespace - /// NOTE: Text.ParseFloat would also use float.Parse() but has additional validation overhead that is skipped here - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float ParseFloatValue(this Text input) - { - return float.Parse(input.ToString(), CultureInfo.InvariantCulture); - } - - /// - /// Parses a double point value from a Text that is already trimed of whitespace - /// NOTE: Text.ParseDouble would also use double.Parse() but has additional validation overhead that is skipped here - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double ParseDoubleValue(this Text input) - { - return double.Parse(input.ToString(), CultureInfo.InvariantCulture); - } - } -} \ No newline at end of file diff --git a/src/Aardvark.Data.Wavefront/WavefrontMaterial.cs b/src/Aardvark.Data.Wavefront/WavefrontMaterial.cs deleted file mode 100644 index 37349a34..00000000 --- a/src/Aardvark.Data.Wavefront/WavefrontMaterial.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Aardvark.Base; - -namespace Aardvark.Data.Wavefront -{ - public class WavefrontMaterial : SymMapBase - { - public static class Property - { - public static readonly Symbol AmbientColor = "AmbientColor"; - public static readonly Symbol EmissiveColor = "EmissiveColor"; - public static readonly Symbol DiffuseColor = "DiffuseColor"; - public static readonly Symbol SpecularColor = "SpecularColor"; - public static readonly Symbol SpecularExponent = "SpecularExponent"; - public static readonly Symbol Opacity = "Opacity"; - public static readonly Symbol TransmissionFilter = "TransmissionFilter"; - public static readonly Symbol IlluminationModel = "IlluminationModel"; - public static readonly Symbol Sharpness = "Sharpness"; - public static readonly Symbol OpticalDensity = "OpticalDensity"; - - public static readonly Symbol AmbientColorMap = "AmbientColorMap"; - public static readonly Symbol DiffuseColorMap = "DiffuseColorMap"; - public static readonly Symbol SpecularColorMap = "SpecularColorMap"; - public static readonly Symbol EmissiveColorMap = "EmissiveColorMap"; - public static readonly Symbol SpecularExponentMap = "SpecularExponentMap"; - public static readonly Symbol OpacityMap = "OpacityMap"; - public static readonly Symbol DecalMap = "DecalMap"; - public static readonly Symbol DisplacementMap = "DisplacementMap"; - public static readonly Symbol BumpMap = "BumpMap"; - public static readonly Symbol NormalMap = "NormalMap"; - - public static readonly Symbol ReflectionMap = "ReflectionMap"; - - public static readonly Symbol Path = "Path"; - } - - public string Name; - - public WavefrontMaterial(string name) - { - Name = name; - } - } -} diff --git a/src/Aardvark.Data.Wavefront/WavefrontObject.cs b/src/Aardvark.Data.Wavefront/WavefrontObject.cs deleted file mode 100644 index 5bde40a3..00000000 --- a/src/Aardvark.Data.Wavefront/WavefrontObject.cs +++ /dev/null @@ -1,226 +0,0 @@ -using Aardvark.Base; -using Aardvark.Geometry; -using FSharp.Data.Adaptive; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; - -namespace Aardvark.Data.Wavefront -{ - public class WavefrontObject - { - public static class Property - { - public static readonly Symbol Vertices = "v"; - public static readonly Symbol Normals = "vn"; - public static readonly Symbol TextureCoordinates = "vt"; - public static readonly Symbol ControlPoints = "vp"; - - public static readonly Symbol Materials = "usemtl"; - public static readonly Symbol Groups = "g"; - - public static readonly Symbol PointSets = "p"; - public static readonly Symbol LineSets = "l"; - public static readonly Symbol FaceSets = "f"; - } - - public class ElementSet - { - public int GroupIndex; - public List VertexIndices = new List(); - public List FirstIndices = new List(0.IntoIEnumerable()); - public List MaterialIndices = new List(); - - public int ElementCount - { - get { return FirstIndices.Count - 1; } - } - } - - public class PointSet : ElementSet - { - } - - public class LineSet : ElementSet - { - /// - /// Min and max number of vertices per line strip - /// - public Range1i VertexCountRange = Range1i.Invalid; - public List TexCoordIndices = new List(); - } - - public class FaceSet : ElementSet - { - /// - /// Min and max number of vertices per face - /// - public Range1i FaceVertexCountRange = Range1i.Invalid; - public List NormalIndices = new List(); - public List TexCoordIndices = new List(); - public List SmoothingGroupIndex = new List(); // Unused at the moment - } - - public List PointsSets { get; } = new List(); - - public List LineSets { get; } = new List(); - - public List FaceSets { get; } = new List(); - - public List Groups { get; } = new List(); - - public List Materials { get; } = new List(); - - public bool DoublePrecisionVertices { get; } - - /// - /// Vertices either in Single or Double precision (V4f or V4d) - /// - public IList Vertices { get; } - - public List Normals { get; } = new List(); - - /// - /// Optional attribute with same length as Vertices, is null of Obj file does not contain colors in form of unofficial extension - /// - public List VertexColors { get; internal set; } // no colors by default - - public List TextureCoordinates { get; } = new List(); - - public List ControlPoints { get; } = new List(); - - /// - /// Creates a WavefrontObject and initializes the Vertices depending on the parameter as floats or double (default) - /// - /// - public WavefrontObject(bool useDoublePositions = true) - { - if (useDoublePositions) - Vertices = new List(); - else - Vertices = new List(); - - DoublePrecisionVertices = useDoublePositions; - } - } - - public static class WavefrontExtensions - { - /// - /// Builds an enumeration of PolyMeshes as that represent the FaceSets in the Wavefront file. - /// The Position attribute is converted to double vectors, as this is required for a PolyMesh. - /// Normals and TextureCoordinates can either remain float or be also converted to double. - /// The default behavior is similar to PolyMeshFromVrml97: V3d Positions, V3f Normals, V2f TexCoords. - /// All meshes point to the same data arrays with different First/VertexIndex arrays. - /// - public static IEnumerable GetFaceSetMeshes(this WavefrontObject obj, bool doubleAttributes = false) - { - var vertices = obj.DoublePrecisionVertices ? - ((List)obj.Vertices).MapToArray(x => x.XYZ) : - ((List)obj.Vertices).MapToArray(x => new V3d(x.XYZ)); - - var vertexColors = obj.VertexColors?.ToArray(); - var normals = obj.Normals.Count > 0 ? doubleAttributes ? - obj.Normals.MapToArray(n => n.ToV3d()) : (Array)obj.Normals.ToArray() : null; - var texCoords = obj.TextureCoordinates.Count > 0 ? doubleAttributes ? - obj.TextureCoordinates.MapToArray(v => v.XY.ToV2d()) : (Array)obj.TextureCoordinates.MapToArray(v => v.XY) : null; - - var materials = obj.Materials.Count > 0 ? obj.Materials.ToArray() : null; - var groups = obj.Groups; - - foreach (var fs in obj.FaceSets) - { - var mesh = new PolyMesh(); - - mesh.PositionArray = vertices; - if (vertexColors != null) - mesh.VertexAttributes.Add(PolyMesh.Property.Colors, vertexColors); - if (fs.GroupIndex >= 0) - mesh.InstanceAttributes.Add(PolyMesh.Property.Name, groups[fs.GroupIndex]); - - var fia = fs.FirstIndices.ToArray(); - var via = fs.VertexIndices.ToArray(); - - var mIndices = fs.MaterialIndices; - var nIndices = fs.NormalIndices; - var tcIndices = fs.TexCoordIndices; - - mesh.FirstIndexArray = fia; - mesh.VertexIndexArray = via; - - if (!materials.IsEmptyOrNull() && !mIndices.IsEmptyOrNull() && mIndices[0] >= 0) // NOTE: >= 0 check assumes that all faces have no normal indices, otherwise the mesh would need to be split - { - if (mIndices.Count != fs.ElementCount) throw new InvalidOperationException(); - mesh.FaceAttributes.Add(PolyMesh.Property.Material, mIndices.ToArray()); - mesh.FaceAttributes.Add(-PolyMesh.Property.Material, materials); - } - - if (normals != null && normals.Length > 0 && !nIndices.IsEmptyOrNull() && nIndices[0] >= 0) // NOTE: >= 0 check assumes that all faces have no normal indices, otherwise the mesh would need to be split - { - if (nIndices.Count != via.Length) throw new InvalidOperationException(); - mesh.FaceVertexAttributes.Add(PolyMesh.Property.Normals, nIndices.ToArray()); - mesh.FaceVertexAttributes.Add(-PolyMesh.Property.Normals, normals); - } - - if (texCoords != null && texCoords.Length > 0 && !tcIndices.IsEmptyOrNull() && tcIndices[0] >= 0) // NOTE: >= 0 check assumes that all faces have no normal indices, otherwise the mesh would need to be split - { - if (tcIndices.Count != via.Length) throw new InvalidOperationException(); - mesh.FaceVertexAttributes.Add(PolyMesh.Property.DiffuseColorCoordinates, tcIndices.ToArray()); - mesh.FaceVertexAttributes.Add(-PolyMesh.Property.DiffuseColorCoordinates, texCoords); - } - - yield return mesh; - } - } - - //public static IEnumerable GetFaceSetGeometry(this WavefrontObject obj, bool simpleTriangulation = true) - //{ - // var vertices = obj.DoublePrecisionVertices ? - // ((List)obj.Vertices).MapToArray(x => new V3f(x.XYZ)) : - // ((List)obj.Vertices).MapToArray(x => x.XYZ); - - // var vertexColors = obj.VertexColors?.ToArray(); - // var normals = obj.Normals.Count > 0 ? (Array)obj.Normals.ToArray() : null; - // var texCoords = obj.TextureCoordinates.Count > 0 ? (Array)obj.TextureCoordinates.MapToArray(v => v.XY) : null; - - // var materials = obj.Materials.Count > 0 ? obj.Materials.ToArray() : null; - // var groups = obj.Groups; - - // foreach (var fs in obj.FaceSets) - // { - // var indexedAttributes = new SymbolDict(); - - // // TODO: attributes are PerFaceVertex -> needs to be convertex to PerVertex: create matching combination of vertex/normal/texCoord/color indices - // // -> 1. create simple triangulation (seed PoylMesh.CreateSimpleTriangleVertexIndexArray) or non-concave polygon triangulation (only used if FaceVertexCountRange.Max > 4, see PolyMesh.TriangulatedCopy) - // // -> 2. create PerVertex attributes (see PolyMesh.GetIndexGeometry) - - // var fia = fs.FirstIndices.ToArray(); - // var via = fs.VertexIndices.ToArray(); - - // var vertexIndexCount = via.Length; // faceBackMap.Length - // var indexArray = PolyMesh.CreateSimpleTriangleVertexIndexArray(fia, via, fs.ElementCount, vertexIndexCount, fs.FaceVertexCountRange); - - // //var mIndices = fs.MaterialIndices; - // //var nIndices = fs.NormalIndices; - // //var tcIndices = fs.TexCoordIndices; - - // //indexedAttributes.Add(DefaultSemantic.Positions, vertices); - // //if (vertexColors != null) - // // indexAttributes.Add(DefaultSemantic.Colors, vertexColors); - // //if (normals != null) - // // indexAttributes.Add(DefaultSemantic.Normals, normals); - // //if (texCoords != null) - // // indexAttributes.Add(DefaultSemantic.DiffuseColorCoordinates, texCoords); - - // // mateirals ??? TODO: materials -> need to create one return mutliple indexed geometries with different index offset/counts ? - - // var singleAttributes = new SymbolDict(); - // if (fs.GroupIndex >= 0) - // singleAttributes.Add(DefaultSemantic.Name, groups[fs.GroupIndex]); - - // yield return new IndexedGeometry(IndexedGeometryMode.TriangleList, indexArray, indexedAttributes, singleAttributes); - // } - //} - } -} diff --git a/src/Aardvark.Data.Wavefront/WavefrontParser.cs b/src/Aardvark.Data.Wavefront/WavefrontParser.cs deleted file mode 100644 index 697cc425..00000000 --- a/src/Aardvark.Data.Wavefront/WavefrontParser.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Collections.Generic; -using Aardvark.Base; - -namespace Aardvark.Data.Wavefront -{ - internal static class WavefrontParser - { - public static void Parse(T parseState, Dictionary>> elementProcessors) where T: StreamParser - { - var elementValues = new List(); - - for( ; parseState.NextLine(); ) - { - var line = parseState.Line; - line = line.WhiteSpaceTrimmed; - if (line.IsEmpty) continue; - - if (line[0] == '#') - continue; - - // read element type - var sep = SkipToWhiteSpace(line); - var elementType = line.SubText(0, sep); - if (elementType.IsEmpty) throw new InvalidOperationException(); - - // go to next element - line = line.SubText(sep).WhiteSpaceAtStartTrimmed; - - var ep = elementProcessors.Get(elementType); - if (ep != null) - { - while (!line.IsEmpty) - { - // read argument - sep = SkipToWhiteSpace(line); - var arg = line.SubText(0, sep); - - // go to next element - line = line.SubText(sep).WhiteSpaceAtStartTrimmed; - - elementValues.Add(arg); - } - try - { - ep(parseState, elementValues); - } - catch (Exception e) - { - Report.Warn("error parsing object element: {0} {1}\n{2}", elementType, String.Join(" ", elementValues), e.Message); - } - } - else - Report.Warn("object element \"{0}\" not supported", elementType); - - elementValues.Clear(); - } - } - - static int SkipToWhiteSpace(Text txt) - { - int pos = 0; - int cnt = txt.Count; - while (pos < cnt) - { - var ch = txt[pos]; - if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') - break; - pos++; - } - return pos; - } - } -} diff --git a/src/Aardvark.Data.Wavefront/paket.references b/src/Aardvark.Data.Wavefront/paket.references deleted file mode 100644 index 54495842..00000000 --- a/src/Aardvark.Data.Wavefront/paket.references +++ /dev/null @@ -1 +0,0 @@ -Aardvark.Build diff --git a/src/Aardvark.Data.Wavefront/paket.template b/src/Aardvark.Data.Wavefront/paket.template deleted file mode 100644 index 9b3adddb..00000000 --- a/src/Aardvark.Data.Wavefront/paket.template +++ /dev/null @@ -1,11 +0,0 @@ -type project -id Aardvark.Data.Wavefront -authors Aardvark Platform Team -owners Aardvark Platform Team -projectUrl https://github.com/aardvark-platform/aardvark.algodat -licenseUrl http://www.gnu.org/licenses/agpl.txt -repositoryType git -repositoryUrl https://github.com/aardvark-platform/aardvark.algodat -description - A wavefront parser. -include-pdbs true \ No newline at end of file