2017-03-15 16:17:06 -07:00
/ *
Copyright ( c ) 2016 , John Lewin
All rights reserved .
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions are met :
1. Redistributions of source code must retain the above copyright notice , this
list of conditions and the following disclaimer .
2. Redistributions in binary form must reproduce the above copyright notice ,
this list of conditions and the following disclaimer in the documentation
and / or other materials provided with the distribution .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies ,
either expressed or implied , of the FreeBSD Project .
* /
2017-07-12 13:37:26 -07:00
using System.IO ;
using System.Linq ;
2017-07-14 13:55:02 -07:00
using System.Threading ;
2017-07-12 13:37:26 -07:00
using System.Threading.Tasks ;
using MatterHackers.Agg ;
2017-08-20 02:34:39 -07:00
using MatterHackers.Agg.Platform ;
2017-03-15 16:17:06 -07:00
using MatterHackers.DataConverters3D ;
2017-07-31 14:55:12 -07:00
using MatterHackers.MatterControl ;
2017-11-14 15:45:23 -08:00
using MatterHackers.MatterControl.Library ;
2019-03-20 11:08:34 -07:00
using MatterHackers.MatterControl.PartPreviewWindow ;
2017-07-12 13:37:26 -07:00
using MatterHackers.MatterControl.Tests.Automation ;
2017-03-15 16:17:06 -07:00
using MatterHackers.MeshVisualizer ;
2018-02-04 16:31:23 -08:00
using MatterHackers.VectorMath ;
2017-03-15 16:17:06 -07:00
using Newtonsoft.Json ;
using NUnit.Framework ;
namespace MatterHackers.PolygonMesh.UnitTests
{
2017-09-17 10:30:32 -07:00
[TestFixture, Category("Agg.PolygonMesh"), RunInApplicationDomain]
2017-03-15 16:17:06 -07:00
public class SceneTests
{
[Test]
public void SaveSimpleScene ( )
{
var scene = new InteractiveScene ( ) ;
2017-10-02 11:28:00 -07:00
scene . Children . Add ( new Object3D ( ) ) ;
2017-03-15 16:17:06 -07:00
string tempPath = GetSceneTempPath ( ) ;
2018-02-06 22:27:46 -08:00
Object3D . AssetsPath = Path . Combine ( tempPath , "Assets" ) ;
2017-03-15 16:17:06 -07:00
string filePath = Path . Combine ( tempPath , "some.mcx" ) ;
2018-02-06 22:27:46 -08:00
scene . Save ( filePath ) ;
2017-03-15 16:17:06 -07:00
Assert . IsTrue ( File . Exists ( filePath ) ) ;
2017-07-14 13:55:02 -07:00
IObject3D loadedItem = Object3D . Load ( filePath , CancellationToken . None ) ;
2017-03-15 16:17:06 -07:00
Assert . IsTrue ( loadedItem . Children . Count = = 1 ) ;
}
2019-03-20 11:08:34 -07:00
[Test]
public async Task AutoArrangeChildrenTests ( )
{
2019-04-19 09:52:49 -07:00
// arrange a single item around the origin
2019-03-20 11:08:34 -07:00
{
var scene = new InteractiveScene ( ) ;
Object3D cube1 ;
scene . Children . Add ( cube1 = new Object3D ( )
{
Mesh = PlatonicSolids . CreateCube ( 20 , 20 , 20 ) ,
Matrix = Matrix4X4 . CreateTranslation ( 34 , 22 , 10 )
} ) ;
Assert . IsTrue ( new AxisAlignedBoundingBox ( 24 , 12 , 0 , 44 , 32 , 20 ) . Equals ( cube1 . GetAxisAlignedBoundingBox ( ) , . 001 ) ) ;
await scene . AutoArrangeChildren ( Vector3 . Zero ) ;
Assert . IsTrue ( new AxisAlignedBoundingBox ( - 10 , - 10 , 0 , 10 , 10 , 20 ) . Equals ( cube1 . GetAxisAlignedBoundingBox ( ) , . 001 ) ) ;
}
2019-04-19 09:52:49 -07:00
// arrange a single item around a typical bed center
2019-03-20 11:08:34 -07:00
{
var scene = new InteractiveScene ( ) ;
Object3D cube1 ;
scene . Children . Add ( cube1 = new Object3D ( )
{
Mesh = PlatonicSolids . CreateCube ( 20 , 20 , 20 ) ,
Matrix = Matrix4X4 . CreateTranslation ( 34 , 22 , 10 )
} ) ;
Assert . IsTrue ( new AxisAlignedBoundingBox ( 24 , 12 , 0 , 44 , 32 , 20 ) . Equals ( cube1 . GetAxisAlignedBoundingBox ( ) , . 001 ) ) ;
await scene . AutoArrangeChildren ( new Vector3 ( 100 , 100 , 0 ) ) ;
Assert . IsTrue ( new AxisAlignedBoundingBox ( 90 , 90 , 0 , 110 , 110 , 20 ) . Equals ( cube1 . GetAxisAlignedBoundingBox ( ) , . 001 ) ) ;
}
2019-04-19 09:52:49 -07:00
// arrange 4 items
2019-03-20 11:08:34 -07:00
{
var scene = new InteractiveScene ( ) ;
for ( int i = 0 ; i < 4 ; i + + )
{
scene . Children . Add ( new Object3D ( )
{
Mesh = PlatonicSolids . CreateCube ( 20 , 20 , 20 ) ,
Matrix = Matrix4X4 . CreateTranslation ( i * 134 , i * - 122 , 10 )
} ) ;
}
var sceneAabb = scene . GetAxisAlignedBoundingBox ( ) ;
2020-07-01 07:50:19 -07:00
Assert . Greater ( sceneAabb . XSize , 160 ) ;
Assert . Greater ( sceneAabb . YSize , 160 ) ;
2019-03-20 11:08:34 -07:00
await scene . AutoArrangeChildren ( Vector3 . Zero ) ;
sceneAabb = scene . GetAxisAlignedBoundingBox ( ) ;
Assert . Less ( sceneAabb . XSize , 60 ) ;
2020-07-01 07:50:19 -07:00
Assert . Less ( sceneAabb . YSize , 75 ) ;
2019-03-20 11:08:34 -07:00
}
2019-04-19 09:52:49 -07:00
// arrange 4 items, starting with 1 selected
2019-03-20 11:08:34 -07:00
{
var scene = new InteractiveScene ( ) ;
Object3D child = null ;
for ( int i = 0 ; i < 4 ; i + + )
{
scene . Children . Add ( child = new Object3D ( )
{
Mesh = PlatonicSolids . CreateCube ( 20 , 20 , 20 ) ,
Matrix = Matrix4X4 . CreateTranslation ( i * 134 , i * - 122 , 10 )
} ) ;
}
scene . SelectedItem = child ;
var sceneAabb = scene . GetAxisAlignedBoundingBox ( ) ;
2020-07-01 07:50:19 -07:00
Assert . Greater ( sceneAabb . XSize , 160 ) ;
Assert . Greater ( sceneAabb . YSize , 160 ) ;
2019-03-20 11:08:34 -07:00
await scene . AutoArrangeChildren ( Vector3 . Zero ) ;
sceneAabb = scene . GetAxisAlignedBoundingBox ( ) ;
Assert . Less ( sceneAabb . XSize , 60 ) ;
2020-07-01 07:50:19 -07:00
Assert . Less ( sceneAabb . YSize , 75 ) ;
2019-03-20 11:08:34 -07:00
}
}
2020-08-16 07:14:33 -07:00
[Test]
public void AmfFilesSaveObjectProperties ( )
{
AssetObject3D . AssetManager = new AssetManager ( ) ;
var scene = new InteractiveScene ( ) ;
scene . Children . Add ( new Object3D
{
Mesh = PlatonicSolids . CreateCube ( 20 , 20 , 20 ) ,
Name = "test1" ,
OutputType = PrintOutputTypes . Support ,
Color = Color . Red ,
MaterialIndex = 2 ,
} ) ;
scene . Children . Add ( new Object3D
{
Mesh = PlatonicSolids . CreateCube ( 20 , 20 , 20 ) ,
Name = "test2" ,
Matrix = Matrix4X4 . CreateTranslation ( 30 , 0 , 0 )
} ) ;
string tempPath = GetSceneTempPath ( ) ;
Object3D . AssetsPath = Path . Combine ( tempPath , "Assets" ) ;
string filePath = Path . Combine ( tempPath , "exportTest.amf" ) ;
scene . SetSelection ( scene . Children . ToList ( ) ) ;
AmfDocument . Save ( scene . SelectedItem , filePath ) ;
Assert . IsTrue ( File . Exists ( filePath ) ) ;
IObject3D loadedItem = Object3D . Load ( filePath , CancellationToken . None ) ;
Assert . IsTrue ( loadedItem . Children . Count = = 2 ) ;
IObject3D item1 = loadedItem . Children . Last ( ) ;
Assert . AreEqual ( "test1" , item1 . Name ) ;
Assert . AreEqual ( PrintOutputTypes . Support , item1 . OutputType ) ;
Assert . AreEqual ( 2 , item1 . MaterialIndex ) ;
Assert . AreEqual ( Color . Red , item1 . Color ) ;
Assert . AreEqual ( 12 , item1 . Mesh . Faces . Count ) ;
var aabb1 = item1 . GetAxisAlignedBoundingBox ( ) ;
Assert . True ( new AxisAlignedBoundingBox ( - 10 , - 10 , - 10 , 10 , 10 , 10 ) . Equals ( aabb1 , . 001 ) ) ;
IObject3D item2 = loadedItem . Children . First ( ) ;
Assert . AreEqual ( "test2" , item2 . Name ) ;
Assert . AreEqual ( Color . White , item2 . Color ) ;
Assert . AreEqual ( 12 , item2 . Mesh . Faces . Count ) ;
var aabb2 = item2 . GetAxisAlignedBoundingBox ( ) ;
Assert . True ( new AxisAlignedBoundingBox ( 20 , - 10 , - 10 , 40 , 10 , 10 ) . Equals ( aabb2 , . 001 ) ) ;
}
2017-03-15 16:17:06 -07:00
[Test]
public void CreatesAndLinksAmfsForUnsavedMeshes ( )
{
2018-03-10 12:23:46 -08:00
AssetObject3D . AssetManager = new AssetManager ( ) ;
2018-03-08 10:36:00 -08:00
2017-03-15 16:17:06 -07:00
var scene = new InteractiveScene ( ) ;
scene . Children . Add ( new Object3D
{
Mesh = PlatonicSolids . CreateCube ( 20 , 20 , 20 )
} ) ;
string tempPath = GetSceneTempPath ( ) ;
string filePath = Path . Combine ( tempPath , "some.mcx" ) ;
2017-07-12 14:47:01 -07:00
Object3D . AssetsPath = Path . Combine ( tempPath , "Assets" ) ;
2018-02-06 22:27:46 -08:00
scene . Save ( filePath ) ;
2017-03-15 16:17:06 -07:00
Assert . IsTrue ( File . Exists ( filePath ) ) ;
2017-07-14 13:55:02 -07:00
IObject3D loadedItem = Object3D . Load ( filePath , CancellationToken . None ) ;
2017-03-15 16:17:06 -07:00
Assert . IsTrue ( loadedItem . Children . Count = = 1 ) ;
IObject3D meshItem = loadedItem . Children . First ( ) ;
Assert . IsTrue ( ! string . IsNullOrEmpty ( meshItem . MeshPath ) ) ;
2017-07-12 14:47:01 -07:00
Assert . IsTrue ( File . Exists ( Path . Combine ( tempPath , "Assets" , meshItem . MeshPath ) ) ) ;
2017-03-15 16:17:06 -07:00
Assert . IsNotNull ( meshItem . Mesh ) ;
Assert . IsTrue ( meshItem . Mesh . Faces . Count > 0 ) ;
}
2017-09-17 10:18:01 -07:00
[Test]
2017-03-15 16:17:06 -07:00
public async Task ResavedSceneRemainsConsistent ( )
{
#if ! __ANDROID__
// Set the static data to point to the directory of MatterControl
2017-08-20 02:34:39 -07:00
AggContext . StaticData = new FileSystemStaticData ( TestContext . CurrentContext . ResolveProjectPath ( 4 , "StaticData" ) ) ;
2017-03-15 16:17:06 -07:00
MatterControlUtilities . OverrideAppDataLocation ( TestContext . CurrentContext . ResolveProjectPath ( 4 ) ) ;
#endif
2018-03-10 12:23:46 -08:00
AssetObject3D . AssetManager = new AssetManager ( ) ;
2017-08-16 05:53:26 -07:00
2017-11-14 15:45:23 -08:00
var sceneContext = new BedConfig ( null ) ;
2017-06-01 09:50:36 -07:00
2017-09-16 01:11:44 -07:00
var scene = sceneContext . Scene ;
2017-03-15 16:17:06 -07:00
scene . Children . Add ( new Object3D
{
Mesh = PlatonicSolids . CreateCube ( 20 , 20 , 20 )
} ) ;
string tempPath = GetSceneTempPath ( ) ;
string filePath = Path . Combine ( tempPath , "some.mcx" ) ;
2017-09-17 11:34:49 -07:00
// Set directory for asset resolution
2018-02-06 22:27:46 -08:00
Object3D . AssetsPath = Path . Combine ( tempPath , "Assets" ) ;
2017-09-17 11:34:49 -07:00
Directory . CreateDirectory ( Object3D . AssetsPath ) ;
2017-03-15 16:17:06 -07:00
// Empty temp folder
2020-08-16 12:12:37 -07:00
foreach ( string tempFile in Directory . GetFiles ( tempPath ) . ToList ( ) )
2017-03-15 16:17:06 -07:00
{
File . Delete ( tempFile ) ;
}
2018-02-06 22:27:46 -08:00
scene . Save ( filePath ) ;
2017-03-15 16:17:06 -07:00
Assert . AreEqual ( 1 , Directory . GetFiles ( tempPath ) . Length , "Only .mcx file should exists" ) ;
Assert . AreEqual ( 1 , Directory . GetFiles ( Path . Combine ( tempPath , "Assets" ) ) . Length , "Only 1 asset should exist" ) ;
2017-11-14 17:55:03 -08:00
var originalFiles = Directory . GetFiles ( tempPath ) . ToArray ( ) ;
2017-09-15 22:34:46 -07:00
2017-11-14 17:55:03 -08:00
// Load the file from disk
2017-07-14 13:55:02 -07:00
IObject3D loadedItem = Object3D . Load ( filePath , CancellationToken . None ) ;
2017-11-14 17:55:03 -08:00
Assert . AreEqual ( 1 , loadedItem . Children . Count ) ;
2017-03-15 16:17:06 -07:00
2017-09-15 22:34:46 -07:00
// Ensure the UI scene is cleared
2017-09-26 12:52:54 -07:00
scene . Children . Modify ( list = > list . Clear ( ) ) ;
2017-09-15 22:34:46 -07:00
// Reload the model
2017-11-14 15:45:23 -08:00
await Task . Run ( ( ) = >
{
sceneContext . Scene . Load ( Object3D . Load ( filePath , CancellationToken . None ) ) ;
} ) ;
2017-03-15 16:17:06 -07:00
2017-09-15 22:34:46 -07:00
// Serialize and compare the two trees
2017-11-14 17:55:03 -08:00
string onDiskData = loadedItem . ToJson ( ) ;
string inMemoryData = scene . ToJson ( ) ;
//File.WriteAllText(@"c:\temp\file-a.txt", onDiskData);
//File.WriteAllText(@"c:\temp\file-b.txt", inMemoryData);
Assert . AreEqual ( inMemoryData , onDiskData , "Serialized content should match" ) ;
2018-03-01 09:56:50 -08:00
Object3D . AssetsPath = Path . Combine ( tempPath , "Assets" ) ;
2017-03-15 16:17:06 -07:00
// Save the scene a second time, validate that things remain the same
2018-02-06 22:27:46 -08:00
scene . Save ( filePath ) ;
2017-11-14 17:55:03 -08:00
onDiskData = loadedItem . ToJson ( ) ;
2017-03-15 16:17:06 -07:00
Assert . IsTrue ( inMemoryData = = onDiskData ) ;
// Verify that no additional files get created on second save
Assert . AreEqual ( 1 , Directory . GetFiles ( tempPath ) . Length , "Only .mcx file should exists" ) ;
Assert . AreEqual ( 1 , Directory . GetFiles ( Path . Combine ( tempPath , "Assets" ) ) . Length , "Only 1 asset should exist" ) ;
}
2018-02-04 16:31:23 -08:00
private readonly int RootMaterialIndex = 1 ;
private readonly int SuperGroupMaterialIndex = 2 ;
private readonly int GroupMaterialIndex = 3 ;
private readonly int RedMaterialIndex = 4 ;
private readonly int GreenMaterialIndex = 5 ;
private readonly int BlueMaterialIndex = 6 ;
private readonly Matrix4X4 RootMatrix = Matrix4X4 . Identity ;
private readonly Matrix4X4 SuperGroupMatrix = Matrix4X4 . CreateScale ( 2 ) ;
private readonly Matrix4X4 GroupMatrix = Matrix4X4 . Identity ;
private readonly Matrix4X4 RedMatrix = Matrix4X4 . CreateTranslation ( 10 , 0 , 0 ) ;
private readonly Matrix4X4 GreenMatrix = Matrix4X4 . CreateTranslation ( 15 , 0 , 0 ) ;
private readonly Matrix4X4 BlueMatrix = Matrix4X4 . CreateTranslation ( 20 , 0 , 0 ) ;
private readonly PrintOutputTypes RootOutputType = PrintOutputTypes . Solid ;
2018-06-01 17:44:46 -07:00
private readonly PrintOutputTypes SuperGroupOutputType = PrintOutputTypes . Solid ;
2018-02-04 16:31:23 -08:00
private readonly PrintOutputTypes GroupOutputType = PrintOutputTypes . Solid ;
private readonly PrintOutputTypes RedOutputType = PrintOutputTypes . Support ;
private readonly PrintOutputTypes GreenOutputType = PrintOutputTypes . Support ;
2018-06-01 17:44:46 -07:00
private readonly PrintOutputTypes BlueOutputType = PrintOutputTypes . Solid ;
2018-02-04 16:31:23 -08:00
public InteractiveScene SampleScene ( )
{
Object3D group ;
var scene = new InteractiveScene ( )
{
Color = Color . Black ,
MaterialIndex = this . RootMaterialIndex ,
OutputType = this . RootOutputType
} ;
var supergroup = new Object3D ( )
{
Name = "SuperGroup" ,
Color = Color . Violet ,
MaterialIndex = this . SuperGroupMaterialIndex ,
Matrix = this . SuperGroupMatrix ,
OutputType = this . SuperGroupOutputType
} ;
scene . Children . Add ( supergroup ) ;
group = new Object3D ( )
{
Name = "GroupA" ,
Color = Color . Pink ,
MaterialIndex = this . GroupMaterialIndex ,
OutputType = this . GroupOutputType
} ;
supergroup . Children . Add ( group ) ;
group . Children . Add ( new Object3D
{
Name = nameof ( Color . Red ) ,
Color = Color . Red ,
MaterialIndex = this . RedMaterialIndex ,
Matrix = this . RedMatrix ,
OutputType = this . RedOutputType
} ) ;
group = new Object3D ( )
{
Name = "GroupB" ,
Color = Color . Pink ,
MaterialIndex = this . GroupMaterialIndex ,
OutputType = this . GroupOutputType
} ;
supergroup . Children . Add ( group ) ;
group . Children . Add ( new Object3D
{
Name = nameof ( Color . Green ) ,
Color = Color . Green ,
MaterialIndex = this . GreenMaterialIndex ,
Matrix = this . GreenMatrix ,
OutputType = this . GreenOutputType
} ) ;
group = new Object3D ( )
{
Name = "GroupB" ,
Color = Color . Pink ,
MaterialIndex = this . GroupMaterialIndex ,
OutputType = this . GroupOutputType
} ;
supergroup . Children . Add ( group ) ;
group . Children . Add ( new Object3D
{
Name = nameof ( Color . Blue ) ,
Color = Color . Blue ,
MaterialIndex = this . BlueMaterialIndex ,
Matrix = this . BlueMatrix ,
OutputType = this . BlueOutputType
} ) ;
return scene ;
}
[Test]
public void WorldColorBasicTest ( )
{
var scene = SampleScene ( ) ;
2018-02-12 15:28:26 -08:00
var superGroup = scene . DescendantsAndSelf ( ) . Where ( d = > d . Name = = "SuperGroup" ) . FirstOrDefault ( ) ;
var redItem = scene . DescendantsAndSelf ( ) . Where ( d = > d . Name = = nameof ( Color . Red ) ) . FirstOrDefault ( ) ;
var greenItem = scene . DescendantsAndSelf ( ) . Where ( d = > d . Name = = nameof ( Color . Green ) ) . FirstOrDefault ( ) ;
var blueItem = scene . DescendantsAndSelf ( ) . Where ( d = > d . Name = = nameof ( Color . Blue ) ) . FirstOrDefault ( ) ;
2018-02-04 16:31:23 -08:00
// Validate root
Assert . AreEqual ( Color . Black , scene . Color , "Color property on root should be Black" ) ;
Assert . AreEqual ( Color . Black , scene . WorldColor ( ) , "WorldColor on root should be Black" ) ;
// Validate red node
Assert . AreEqual ( Color . Red , redItem . Color , "Color property on node should be Red" ) ;
Assert . AreEqual ( Color . Pink , redItem . WorldColor ( redItem . Parent ) , "WorldColor on Red up to parent node should be Pink" ) ;
Assert . AreEqual ( Color . Violet , redItem . WorldColor ( superGroup ) , "WorldColor on Red up to supergroup should be Violet" ) ;
// Validate green node
Assert . AreEqual ( Color . Green , greenItem . Color , "Color property on node should be Green" ) ;
Assert . AreEqual ( Color . Pink , greenItem . WorldColor ( greenItem . Parent ) , "WorldColor on Green up to parent node should be Pink" ) ;
Assert . AreEqual ( Color . Violet , greenItem . WorldColor ( superGroup ) , "WorldColor on Green up to supergroup should be Violet" ) ;
// Validate green node
Assert . AreEqual ( Color . Blue , blueItem . Color , "Color property on node should be Green" ) ;
Assert . AreEqual ( Color . Pink , blueItem . WorldColor ( blueItem . Parent ) , "WorldColor on Blue up to parent node should be Pink" ) ;
Assert . AreEqual ( Color . Violet , blueItem . WorldColor ( superGroup ) , "WorldColor on Blue up to supergroup should be Violet" ) ;
// Validate WorldColor with null param
Assert . AreEqual ( Color . Black , redItem . WorldColor ( null ) , "WorldColor on Red with null param should be root color (Black)" ) ;
}
[Test]
public void WorldMaterialIndexBasicTest ( )
{
var scene = SampleScene ( ) ;
2018-02-12 15:28:26 -08:00
var superGroup = scene . DescendantsAndSelf ( ) . Where ( d = > d . Name = = "SuperGroup" ) . FirstOrDefault ( ) ;
var redItem = scene . DescendantsAndSelf ( ) . Where ( d = > d . Name = = nameof ( Color . Red ) ) . FirstOrDefault ( ) ;
var greenItem = scene . DescendantsAndSelf ( ) . Where ( d = > d . Name = = nameof ( Color . Green ) ) . FirstOrDefault ( ) ;
var blueItem = scene . DescendantsAndSelf ( ) . Where ( d = > d . Name = = nameof ( Color . Blue ) ) . FirstOrDefault ( ) ;
2018-02-04 16:31:23 -08:00
// Validate root
Assert . AreEqual ( this . RootMaterialIndex , scene . MaterialIndex , "MaterialIndex property on root should be RootMaterialIndex" ) ;
Assert . AreEqual ( this . RootMaterialIndex , scene . WorldMaterialIndex ( ) , "WorldMaterialIndex on root should be RootMaterialIndex" ) ;
// Validate red node
Assert . AreEqual ( this . RedMaterialIndex , redItem . MaterialIndex , "MaterialIndex property on node should be RedMaterialIndex" ) ;
Assert . AreEqual ( this . GroupMaterialIndex , redItem . WorldMaterialIndex ( redItem . Parent ) , "WorldMaterialIndex on Red up to parent node should be GroupMaterialIndex" ) ;
Assert . AreEqual ( this . SuperGroupMaterialIndex , redItem . WorldMaterialIndex ( superGroup ) , "WorldMaterialIndex on Red up to supergroup should be SuperGroupMaterialIndex" ) ;
// Validate green node
Assert . AreEqual ( this . GreenMaterialIndex , greenItem . MaterialIndex , "MaterialIndex property on node should be GreenMaterialIndex" ) ;
Assert . AreEqual ( this . GroupMaterialIndex , greenItem . WorldMaterialIndex ( greenItem . Parent ) , "WorldMaterialIndex on Green up to parent node should be GroupMaterialIndex" ) ;
Assert . AreEqual ( this . SuperGroupMaterialIndex , greenItem . WorldMaterialIndex ( superGroup ) , "WorldMaterialIndex on Green up to supergroup should be SuperGroupMaterialIndex" ) ;
// Validate green node
Assert . AreEqual ( this . BlueMaterialIndex , blueItem . MaterialIndex , "MaterialIndex property on node should be BlueMaterialIndex" ) ;
Assert . AreEqual ( this . GroupMaterialIndex , blueItem . WorldMaterialIndex ( blueItem . Parent ) , "WorldMaterialIndex on Blue up to parent node should be GroupMaterialIndex" ) ;
Assert . AreEqual ( this . SuperGroupMaterialIndex , blueItem . WorldMaterialIndex ( superGroup ) , "WorldMaterialIndex on Blue up to supergroup should be SuperGroupMaterialIndex" ) ;
// Validate MaterialIndex with null param
Assert . AreEqual ( this . RootMaterialIndex , redItem . WorldMaterialIndex ( null ) , "WorldMaterialIndex on Red with null param should be root color (RootMaterialIndex)" ) ;
}
[Test]
public void WorldMatrixBasicTest ( )
{
var scene = SampleScene ( ) ;
2018-02-12 15:28:26 -08:00
var superGroup = scene . DescendantsAndSelf ( ) . Where ( d = > d . Name = = "SuperGroup" ) . FirstOrDefault ( ) ;
var redItem = scene . DescendantsAndSelf ( ) . Where ( d = > d . Name = = nameof ( Color . Red ) ) . FirstOrDefault ( ) ;
var greenItem = scene . DescendantsAndSelf ( ) . Where ( d = > d . Name = = nameof ( Color . Green ) ) . FirstOrDefault ( ) ;
var blueItem = scene . DescendantsAndSelf ( ) . Where ( d = > d . Name = = nameof ( Color . Blue ) ) . FirstOrDefault ( ) ;
2018-02-04 16:31:23 -08:00
// Validate root
Assert . AreEqual ( this . RootMatrix , scene . Matrix , "Matrix property on root should be RootMatrix" ) ;
Assert . AreEqual ( this . RootMatrix , scene . WorldMatrix ( ) , "WorldMatrix on root should be RootMatrix" ) ;
// Validate red node
Assert . AreEqual ( this . RedMatrix , redItem . Matrix , "Matrix property on node should be RedMatrix" ) ;
Assert . AreEqual ( redItem . Matrix * this . GroupMatrix , redItem . WorldMatrix ( redItem . Parent ) , "WorldMatrix on Red up to parent node should be GroupMatrix" ) ;
Assert . AreEqual ( this . RedMatrix * this . GroupMatrix * this . SuperGroupMatrix , redItem . WorldMatrix ( superGroup ) , "WorldMatrix on Red up to supergroup invalid" ) ;
// Validate green node
Assert . AreEqual ( this . GreenMatrix , greenItem . Matrix , "Matrix property on node should be GreenMatrix" ) ;
Assert . AreEqual ( this . GreenMatrix * this . GroupMatrix , greenItem . WorldMatrix ( greenItem . Parent ) , "WorldMatrix on Green up to parent node should be GroupMatrix" ) ;
Assert . AreEqual ( this . GreenMatrix * this . GroupMatrix * this . SuperGroupMatrix , greenItem . WorldMatrix ( superGroup ) , "WorldMatrix on Green up to supergroup should be SuperGroupMatrix" ) ;
// Validate green node
Assert . AreEqual ( this . BlueMatrix , blueItem . Matrix , "Matrix property on node should be BlueMatrix" ) ;
Assert . AreEqual ( this . BlueMatrix * this . GroupMatrix , blueItem . WorldMatrix ( blueItem . Parent ) , "WorldMatrix on Blue up to parent node should be GroupMatrix" ) ;
Assert . AreEqual ( this . BlueMatrix * this . GroupMatrix * this . SuperGroupMatrix , blueItem . WorldMatrix ( superGroup ) , "WorldMatrix on Blue up to supergroup should be SuperGroupMatrix" ) ;
// Validate Matrix with null param
Assert . AreEqual ( this . RedMatrix * this . GroupMatrix * this . SuperGroupMatrix , redItem . WorldMatrix ( null ) , "WorldMatrix on Red with null param should be root color (RootMatrix)" ) ;
}
[Test]
public void WorldOutputTypeBasicTest ( )
{
var scene = SampleScene ( ) ;
2018-02-12 15:28:26 -08:00
var superGroup = scene . DescendantsAndSelf ( ) . Where ( d = > d . Name = = "SuperGroup" ) . FirstOrDefault ( ) ;
var redItem = scene . DescendantsAndSelf ( ) . Where ( d = > d . Name = = nameof ( Color . Red ) ) . FirstOrDefault ( ) ;
var greenItem = scene . DescendantsAndSelf ( ) . Where ( d = > d . Name = = nameof ( Color . Green ) ) . FirstOrDefault ( ) ;
var blueItem = scene . DescendantsAndSelf ( ) . Where ( d = > d . Name = = nameof ( Color . Blue ) ) . FirstOrDefault ( ) ;
2018-02-04 16:31:23 -08:00
// Validate root
Assert . AreEqual ( this . RootOutputType , scene . OutputType , "OutputType property on root should be RootOutputType" ) ;
Assert . AreEqual ( this . RootOutputType , scene . WorldOutputType ( ) , "WorldOutputType on root should be RootOutputType" ) ;
// Validate red node
Assert . AreEqual ( this . RedOutputType , redItem . OutputType , "OutputType property on node should be RedOutputType" ) ;
Assert . AreEqual ( this . GroupOutputType , redItem . WorldOutputType ( redItem . Parent ) , "WorldOutputType on Red up to parent node should be GroupOutputType" ) ;
Assert . AreEqual ( this . SuperGroupOutputType , redItem . WorldOutputType ( superGroup ) , "WorldOutputType on Red up to supergroup should be SuperGroupOutputType" ) ;
// Validate green node
Assert . AreEqual ( this . GreenOutputType , greenItem . OutputType , "OutputType property on node should be GreenOutputType" ) ;
Assert . AreEqual ( this . GroupOutputType , greenItem . WorldOutputType ( greenItem . Parent ) , "WorldOutputType on Green up to parent node should be GroupOutputType" ) ;
Assert . AreEqual ( this . SuperGroupOutputType , greenItem . WorldOutputType ( superGroup ) , "WorldOutputType on Green up to supergroup should be SuperGroupOutputType" ) ;
// Validate green node
Assert . AreEqual ( this . BlueOutputType , blueItem . OutputType , "OutputType property on node should be BlueOutputType" ) ;
Assert . AreEqual ( this . GroupOutputType , blueItem . WorldOutputType ( blueItem . Parent ) , "WorldOutputType on Blue up to parent node should be GroupOutputType" ) ;
Assert . AreEqual ( this . SuperGroupOutputType , blueItem . WorldOutputType ( superGroup ) , "WorldOutputType on Blue up to supergroup should be SuperGroupOutputType" ) ;
// Validate OutputType with null param
Assert . AreEqual ( this . RootOutputType , redItem . WorldOutputType ( null ) , "WorldOutputType on Red with null param should be root color (RootOutputType)" ) ;
}
[Test]
public void WorldFunctionNonExistingAncestorOverride ( )
{
var scene = SampleScene ( ) ;
2018-02-12 15:28:26 -08:00
var redItem = scene . DescendantsAndSelf ( ) . Where ( d = > d . Name = = nameof ( Color . Red ) ) . FirstOrDefault ( ) ;
2018-02-04 16:31:23 -08:00
var nonAncestor = new Object3D ( ) ;
// ************************************* WorldColor *************************************
// Validate root
Assert . AreEqual ( Color . Black , scene . Color , "Color property on root should be Black" ) ;
Assert . AreEqual ( Color . Black , scene . WorldColor ( ) , "WorldColor on root should be Black" ) ;
// Validate red node
Assert . AreEqual ( Color . Red , redItem . Color , "Color property on node should be Red" ) ;
// Validate WorldColor with non-ancestor param
Assert . AreEqual ( Color . Black , redItem . WorldColor ( nonAncestor ) , "WorldColor on Red with non-ancestor should be root color (Black)" ) ;
// ************************************* MaterialIndex *************************************
// Validate root
Assert . AreEqual ( this . RootMaterialIndex , scene . MaterialIndex , "MaterialIndex property on root should be RootMaterialIndex" ) ;
Assert . AreEqual ( this . RootMaterialIndex , scene . WorldMaterialIndex ( ) , "WorldMaterialIndex on root should be RootMaterialIndex" ) ;
// Validate red node
Assert . AreEqual ( this . RedMaterialIndex , redItem . MaterialIndex , "Color property on node should be Red" ) ;
// Validate WorldColor with non-ancestor param
Assert . AreEqual ( this . RootMaterialIndex , redItem . WorldMaterialIndex ( nonAncestor ) , "WorldMaterialIndex on Red with non-ancestor should be RootMaterialIndex" ) ;
// ************************************* WorldMaxtrix *************************************
// Validate root
Assert . AreEqual ( this . RootMatrix , scene . Matrix , "Matrix property on root should be RootMatrix" ) ;
Assert . AreEqual ( this . RootMatrix , scene . WorldMatrix ( ) , "WorldMatrix on root should be RootMatrix" ) ;
// Validate red node
Assert . AreEqual ( this . RedMatrix , redItem . Matrix , "Matrix property on node should be RedMatrix" ) ;
// Validate WorldColor with non-ancestor param
2018-02-04 17:00:10 -08:00
Assert . AreEqual ( this . RedMatrix * this . GroupMatrix * this . SuperGroupMatrix , redItem . WorldMatrix ( nonAncestor ) , "WorldMatrix on Red with non-ancestor should be RootMaterialIndex" ) ;
2018-02-04 16:31:23 -08:00
// ************************************* WorldOutputType *************************************
// Validate root
Assert . AreEqual ( this . RootOutputType , scene . OutputType , "OutputType property on root should be RootOutputType" ) ;
Assert . AreEqual ( this . RootOutputType , scene . WorldOutputType ( ) , "WorldOutputType on root should be RootOutputType" ) ;
// Validate red node
Assert . AreEqual ( this . RedOutputType , redItem . OutputType , "Color property on node should be Red" ) ;
// Validate WorldColor with non-ancestor param
Assert . AreEqual ( this . RootOutputType , redItem . WorldOutputType ( nonAncestor ) , "WorldOutputType on Red with non-ancestor should be RootOutputType" ) ;
}
2017-03-15 16:17:06 -07:00
public static string GetSceneTempPath ( )
{
2017-07-12 13:37:26 -07:00
string tempPath = TestContext . CurrentContext . ResolveProjectPath ( 4 , "Tests" , "temp" , "scenetests" ) ;
2017-03-15 16:17:06 -07:00
Directory . CreateDirectory ( tempPath ) ;
2017-07-12 13:37:26 -07:00
2017-03-15 16:17:06 -07:00
return tempPath ;
}
}
}