|
struct Test_HairFromGuidesModifier
|
|
(
|
|
-- Tests that manually changing guide count in MaxScript makes the resulting guides to be recomputed
|
|
function Test_VertexDistributionWithRandomGuideDistribution =
|
|
(
|
|
-- Create a plane with 2x2 segments so we have 9 vertices all together
|
|
local distributionObject = Plane lengthsegs:2 widthsegs:2
|
|
|
|
-- Copy the vertex positions of the plane into an array, we will compare them to hair roots later on
|
|
local meshVertices = #();
|
|
meshVertices.count = distributionObject.mesh.vertices.count
|
|
for i = 1 to distributionObject.mesh.vertices.count do
|
|
meshVertices[i] = distributionObject.mesh.vertices[i].position
|
|
|
|
max modify mode
|
|
|
|
-- Add guides from surface, make sure it has a random distribution
|
|
select distributionObject
|
|
guidesFromSurfaceModifier = Ox_Guides_from_Surface()
|
|
TestUtilities.SetGuidesFromMeshDefaults guidesFromSurfaceModifier
|
|
|
|
modPanel.addModToSelection guidesFromSurfaceModifier
|
|
|
|
-- Add hair from guides, and set its distribution mode to vertex
|
|
hairFromGuidesModifier = Ox_Hair_from_Guides()
|
|
modPanel.addModToSelection hairFromGuidesModifier
|
|
hairFromGuidesModifier.method = 4
|
|
|
|
-- Need to collapse the stack to get access to hair
|
|
convertTo distributionObject HairObject
|
|
myHair = distributionObject.GetHair()
|
|
|
|
-- The position of each hair root should coincide with the position of each of the plane's vertices
|
|
EAssert.AreEqual ( meshVertices.count ) ( myHair.NumRoots() )
|
|
|
|
for i = 1 to meshVertices.count do
|
|
(
|
|
rootPoint = myHair.GetPointT ( i - 1 ) 0
|
|
|
|
-- The root coordinate has to be one of the vertex coordinates of the original mesh
|
|
EAssert.IsTrue( ( findItem meshVertices rootPoint ) != undefined )
|
|
)
|
|
|
|
-- Cleanup
|
|
delete distributionObject
|
|
),
|
|
|
|
function Test_HairFromGuidesInstancedStrandsWithMeshFromStrandsAndRendering =
|
|
(
|
|
local sphereObject = Sphere radius:10 pos:[0,0,0] isSelected:on
|
|
hairObject = SetupQuickOrnatrixHairFromSelection()
|
|
|
|
-- Initialize distribution parameters
|
|
TestUtilities.SetGuidesFromMeshDefaults( hairObject.modifiers[#Ox_Guides_from_Surface] )
|
|
|
|
-- In the Hair From Guides modifier turn on the "instanced strands" option
|
|
hairFromGuidesModifier = OxFindSelOccurenceOf #Ox_Hair_from_Guides instance:hairObject
|
|
hairFromGuidesModifier.instance = true
|
|
|
|
-- Test rendering of instanced strands with built-in fast raytracer, it should not cause a crash
|
|
-- Set render count to a small number so that the test renders quicker
|
|
hairFromGuidesModifier.denseCount = 100
|
|
|
|
-- Add Ox fast raytrace effect and render
|
|
AddOrnatrixFastRaytraceEffectWithSelectedHair()
|
|
render()
|
|
|
|
-- Add Mesh From Strands modifier, it should not cause a crash
|
|
OxAddModifierEx Ox_Mesh_From_Strands targetNode:hairObject
|
|
|
|
-- Cleanup
|
|
delete sphereObject
|
|
delete hairObject
|
|
),
|
|
|
|
function Test_HavingTwoGuidesCausesNoErrorWhenHairInterpolatesBetweenThreeGuides =
|
|
(
|
|
local distributionObject = Plane()
|
|
|
|
max modify mode
|
|
|
|
select distributionObject
|
|
local guidesFromSurfaceModifier = Ox_Guides_from_Surface()
|
|
TestUtilities.SetGuidesFromMeshDefaults guidesFromSurfaceModifier
|
|
|
|
modPanel.addModToSelection guidesFromSurfaceModifier
|
|
|
|
-- In guides from surface modifier set number of guides to 2
|
|
distributionObject.modifiers[#Ox_Guides_from_Surface].count = 2
|
|
|
|
modPanel.addModToSelection (Ox_Hair_from_Guides())
|
|
|
|
-- Test 1: Set interpolation mode to affine. This should not cause any errors.
|
|
distributionObject.modifiers[#Ox_Hair_from_Guides].interpMeth = 1
|
|
|
|
-- Cleanup
|
|
delete distributionObject
|
|
),
|
|
|
|
function Test_RootUpdateOnDistributionMapChangeWhenInCreateMode =
|
|
(
|
|
local distributionObject = Plane lengthsegs:1 widthsegs:1
|
|
max modify mode
|
|
|
|
-- Setup guides with surface comb
|
|
select distributionObject
|
|
guidesFromSurfaceModifier = Ox_Guides_from_Surface()
|
|
guidesFromSurfaceModifier.method = 4
|
|
guidesFromSurfaceModifier.numSegs = 2
|
|
modPanel.addModToSelection guidesFromSurfaceModifier
|
|
|
|
local hairFromGuidesModifierInstance = Ox_Hair_from_Guides()
|
|
modPanel.addModToSelection hairFromGuidesModifierInstance
|
|
|
|
local distributionMap = Checker()
|
|
hairFromGuidesModifierInstance.distrMap = distributionMap
|
|
|
|
-- Record number of roots at present
|
|
local hairCopy = instance distributionObject
|
|
convertTo hairCopy HairObject
|
|
myHair = hairCopy.GetHair()
|
|
initialRootCount = (myHair.NumRoots())
|
|
delete hairCopy
|
|
|
|
-- Go out of sub-object mode
|
|
max create mode
|
|
|
|
-- Change the checker map to be all black
|
|
distributionMap.color1 = color 255 255 255
|
|
|
|
-- Number of generated guides should have changed
|
|
hairCopy = instance distributionObject
|
|
convertTo hairCopy HairObject
|
|
myHair = hairCopy.GetHair()
|
|
EAssert.AreNotEqual initialRootCount (myHair.NumRoots())
|
|
delete hairCopy
|
|
|
|
-- Cleanup
|
|
delete distributionObject
|
|
),
|
|
|
|
-- Tests for a bug where viewport nitrous preview doesn't update vertex indices when hair count goes up
|
|
function Test_ChangeDistributionTypes =
|
|
(
|
|
local distributionObject = Plane lengthsegs:1 widthsegs:1
|
|
max modify mode
|
|
|
|
-- Setup guides with surface comb
|
|
select distributionObject
|
|
local guidesFromSurfaceModifier = Ox_Guides_from_Surface()
|
|
modPanel.addModToSelection guidesFromSurfaceModifier
|
|
|
|
local hairFromGuidesModifierInstance = Ox_Hair_from_Guides()
|
|
modPanel.addModToSelection hairFromGuidesModifierInstance
|
|
|
|
-- Switch to "guides as hair" method and then to random distribution, which will increase the hair count
|
|
hairFromGuidesModifierInstance.method = 4
|
|
completeRedraw()
|
|
|
|
hairFromGuidesModifierInstance.method = 1
|
|
completeRedraw()
|
|
|
|
hairFromGuidesModifierInstance.method = 5
|
|
completeRedraw()
|
|
|
|
hairFromGuidesModifierInstance.method = 3
|
|
completeRedraw()
|
|
|
|
-- No crash should have occured
|
|
|
|
-- Cleanup
|
|
delete distributionObject
|
|
),
|
|
|
|
-- Tests that the same hair from guides modifier can be applied to two objects at the same time
|
|
function Test_ModifierInstancing =
|
|
(
|
|
local distributionObject1 = Plane lengthsegs:1 widthsegs:1
|
|
local distributionObject2 = Plane lengthsegs:1 widthsegs:1
|
|
max modify mode
|
|
|
|
-- Setup guides on both objects
|
|
select distributionObject1
|
|
local guidesFromSurfaceModifierInstance = Ox_Guides_from_Surface()
|
|
TestUtilities.SetGuidesFromMeshDefaults guidesFromSurfaceModifierInstance
|
|
modPanel.addModToSelection guidesFromSurfaceModifierInstance
|
|
|
|
select distributionObject2
|
|
local guidesFromSurfaceModifierInstance = Ox_Guides_from_Surface()
|
|
TestUtilities.SetGuidesFromMeshDefaults guidesFromSurfaceModifierInstance
|
|
modPanel.addModToSelection guidesFromSurfaceModifierInstance
|
|
|
|
-- Create a single hair from guides modifier and add it to both objects
|
|
local hairFromGuidesModifierInstance = Ox_Hair_From_Guides()
|
|
hairFromGuidesModifierInstance.count = 10
|
|
select distributionObject1
|
|
modPanel.addModToSelection hairFromGuidesModifierInstance
|
|
select distributionObject2
|
|
modPanel.addModToSelection hairFromGuidesModifierInstance
|
|
|
|
-- Change the hair count to 5 and make sure that both hair objects with the instanced modifier now have 5 hairs
|
|
hairFromGuidesModifierInstance.count = 5
|
|
|
|
local hairCopy = instance distributionObject1
|
|
convertTo hairCopy HairObject
|
|
myHair = hairCopy.GetHair()
|
|
EAssert.AreEqual 5 (myHair.NumRoots())
|
|
delete hairCopy
|
|
|
|
hairCopy = instance distributionObject2
|
|
convertTo hairCopy HairObject
|
|
myHair = hairCopy.GetHair()
|
|
EAssert.AreEqual 5 (myHair.NumRoots())
|
|
delete hairCopy
|
|
|
|
-- Cleanup
|
|
delete distributionObject1
|
|
delete distributionObject2
|
|
),
|
|
|
|
--Tests for correct synchronisation between vewport count, percentage, and render count
|
|
function Test_ViewportAndRenderHairCount =
|
|
(
|
|
local distributionObject1 = Plane lengthsegs:1 widthsegs:1
|
|
max modify mode
|
|
|
|
-- Setup guides on object
|
|
select distributionObject1
|
|
local guidesFromSurfaceModifierInstance = Ox_Guides_from_Surface()
|
|
TestUtilities.SetGuidesFromMeshDefaults guidesFromSurfaceModifierInstance
|
|
modPanel.addModToSelection guidesFromSurfaceModifierInstance
|
|
|
|
-- Create a hair from guides modifier and add it to object
|
|
local hairFromGuidesModifierInstance = Ox_Hair_From_Guides()
|
|
hairFromGuidesModifierInstance.count = 2000
|
|
hairFromGuidesModifierInstance.denseCount = 10000
|
|
select distributionObject1
|
|
modPanel.addModToSelection hairFromGuidesModifierInstance
|
|
|
|
--Test Percentage
|
|
EAssert.AreEqual 20.0 hairFromGuidesModifierInstance.viewCountPercentage
|
|
|
|
--Test Viewport Count by changing Percentage and Render Count
|
|
hairFromGuidesModifierInstance.viewCountPercentage = 30.0
|
|
hairFromGuidesModifierInstance.denseCount = 10000
|
|
|
|
--Test Viewport Count
|
|
EAssert.AreNearEqual 3000 hairFromGuidesModifierInstance.count
|
|
|
|
-- Cleanup
|
|
delete distributionObject1
|
|
),
|
|
|
|
function Test_DisplacementMapAndOffset =
|
|
(
|
|
-- Create a plane with 1x1 segments (so that there are are no vertices going exactly down the middle)
|
|
local distributionObject = Plane lengthsegs:1 widthsegs:1
|
|
max modify mode
|
|
|
|
-- Setup guides with surface comb
|
|
select distributionObject
|
|
local guidesFromSurfaceModifier = Ox_Guides_from_Surface()
|
|
TestUtilities.SetGuidesFromMeshDefaults guidesFromSurfaceModifier
|
|
guidesFromSurfaceModifier.guideLength = 10
|
|
guidesFromSurfaceModifier.randomness = 0
|
|
guidesFromSurfaceModifier.NumSegs = 2
|
|
modPanel.addModToSelection guidesFromSurfaceModifier
|
|
|
|
-- Assign Hair From Guides Modifier
|
|
local hairFromGuidesModifierInstance = Ox_Hair_from_Guides()
|
|
hairFromGuidesModifierInstance.method = 0
|
|
hairFromGuidesModifierInstance.count = 10
|
|
modPanel.addModToSelection hairFromGuidesModifierInstance
|
|
|
|
-- Without Displacement
|
|
hairFromGuidesModifierInstance.displacementMap = undefined
|
|
hairFromGuidesModifierInstance.displacementOffset = 0
|
|
guidesCopy = instance distributionObject
|
|
convertTo guidesCopy HairObject
|
|
myHair = guidesCopy.GetHair()
|
|
ZeroDisplaceTip = 0
|
|
ZeroDisplaceRoot = 0
|
|
for i = 0 to ( myHair.NumRoots() - 1 ) do
|
|
(
|
|
hairRootPoint = myHair.GetPointT i 0
|
|
hairTipPoint = myHair.GetPointT i 1
|
|
ZeroDisplaceTip += hairTipPoint.z
|
|
ZeroDisplaceRoot += hairRootPoint.z
|
|
)
|
|
|
|
EAssert.AreNearEqual 0 ( ZeroDisplaceRoot )
|
|
|
|
--With Displacement (with middle grey map and double Guide's Length as offset, it should be at the top of each strands without displacement)
|
|
DisplacementMap = Checker ()
|
|
DisplacementMap.color1 = DisplacementMap.color2 = (color 255 255 255) / 2
|
|
hairFromGuidesModifierInstance.displacementMap = DisplacementMap
|
|
hairFromGuidesModifierInstance.displacementOffset = guidesFromSurfaceModifier.guideLength * 2
|
|
guidesCopy2 = instance distributionObject
|
|
convertTo guidesCopy2 HairObject
|
|
myHair2 = guidesCopy2.GetHair()
|
|
DisplaceRoot = 0
|
|
for i = 0 to ( myHair2.NumRoots() - 1 ) do
|
|
(
|
|
hairRootPoint = myHair2.GetPointT i 0
|
|
DisplaceRoot += hairRootPoint.z
|
|
)
|
|
|
|
EAssert.AreNearEqual ZeroDisplaceTip DisplaceRoot
|
|
|
|
-- Cleanup
|
|
delete distributionObject
|
|
delete guidesCopy
|
|
delete guidesCopy2
|
|
),
|
|
|
|
function Test_DisplacementMapChannels =
|
|
(
|
|
-- Create a plane with 1x1 segments (so that there are are no vertices going exactly down the middle)
|
|
distributionObject = Plane lengthsegs:1 widthsegs:1
|
|
max modify mode
|
|
|
|
-- Create Mapping Channels
|
|
select distributionObject
|
|
for i = 1 to 2 do
|
|
(
|
|
uvwMapModifier = Uvwmap ()
|
|
uvwMapModifier.mapChannel = i
|
|
uvwMapModifier.length = distributionObject.length / i
|
|
uvwMapModifier.width = distributionObject.width / i
|
|
modPanel.addModToSelection uvwMapModifier
|
|
)
|
|
|
|
-- Setup guides with surface comb
|
|
select distributionObject
|
|
guidesFromSurfaceModifier = Ox_Guides_from_Surface()
|
|
guidesFromSurfaceModifier.method = 2
|
|
guidesFromSurfaceModifier.uvChannel = 1
|
|
guidesFromSurfaceModifier.count = 100
|
|
guidesFromSurfaceModifier.guideLength = 10
|
|
guidesFromSurfaceModifier.randomness = 0
|
|
guidesFromSurfaceModifier.NumSegs = 2
|
|
modPanel.addModToSelection guidesFromSurfaceModifier
|
|
|
|
hairFromGuidesModifierInstance = Ox_Hair_from_Guides()
|
|
modPanel.addModToSelection hairFromGuidesModifierInstance
|
|
|
|
DisplacementMap = Checker ()
|
|
DisplacementMap.color1 = black
|
|
DisplacementMap.color2 = white
|
|
hairFromGuidesModifierInstance.displacementMap = DisplacementMap
|
|
hairFromGuidesModifierInstance.displacementOffset = guidesFromSurfaceModifier.guideLength
|
|
|
|
--Bake 1-st Mapping Channel
|
|
hairFromGuidesModifierInstance.uvChannel = 1
|
|
guidesCopy1 = instance distributionObject
|
|
convertTo guidesCopy1 HairObject
|
|
myHair1 = guidesCopy1.GetHair()
|
|
|
|
--Bake 2-nd Mapping Channel
|
|
hairFromGuidesModifierInstance.uvChannel = 2
|
|
guidesCopy2 = instance distributionObject
|
|
convertTo guidesCopy2 HairObject
|
|
myHair2 = guidesCopy2.GetHair()
|
|
|
|
--Hairs Count should be the same
|
|
EAssert.AreEqual ( myHair1.NumRoots() ) ( myHair2.NumRoots() )
|
|
|
|
--Check for matching, if Mapping channel isn't affected, 100% points will be at the same position
|
|
matchedPoints = 0
|
|
for i = 0 to ( myHair1.NumRoots() - 1 ) do
|
|
(
|
|
RootPoint1 = myHair1.GetPointT i 0
|
|
RootPoint2 = myHair2.GetPointT i 0
|
|
if ( RootPoint1 == RootPoint2 ) then
|
|
(
|
|
matchedPoints += 1
|
|
)
|
|
)
|
|
EAssert.AreNotEqual matchedPoints ( myHair1.NumRoots() )
|
|
|
|
-- Cleanup
|
|
delete distributionObject
|
|
delete guidesCopy1
|
|
delete guidesCopy2
|
|
),
|
|
|
|
function Test_RenderHairCaching =
|
|
(
|
|
-- Create a plane with 1x1 segments
|
|
local distributionObject = Plane lengthsegs:1 widthsegs:1
|
|
max modify mode
|
|
|
|
-- Setup guides with surface comb
|
|
select distributionObject
|
|
local guidesFromSurfaceModifier = Ox_Guides_from_Surface()
|
|
TestUtilities.SetGuidesFromMeshDefaults guidesFromSurfaceModifier
|
|
guidesFromSurfaceModifier.method = 4
|
|
guidesFromSurfaceModifier.NumSegs = 2
|
|
modPanel.addModToSelection guidesFromSurfaceModifier
|
|
|
|
-- Assign Hair From Guides Modifier
|
|
local hairFromGuidesModifierInstance = Ox_Hair_from_Guides()
|
|
hairFromGuidesModifierInstance.method = 0
|
|
hairFromGuidesModifierInstance.count = 10
|
|
hairFromGuidesModifierInstance.denseCount = 100
|
|
modPanel.addModToSelection hairFromGuidesModifierInstance
|
|
|
|
EAssert.IsFalse (hairFromGuidesModifierInstance.GetCacheRenderHairPositions())
|
|
|
|
hairFromGuidesModifierInstance.rememberPositions = true
|
|
|
|
EAssert.IsTrue (hairFromGuidesModifierInstance.GetCacheRenderHairPositions())
|
|
|
|
-- Cleanup
|
|
delete distributionObject
|
|
)
|
|
)
|
|
|
|
EUnit.AddTestClass Test_HairFromGuidesModifier
|
|
ok
|