Project

General

Profile

Hair from Guides Modifier » Test_HairFromGuidesModifier.ms

Marsel Khadiyev, 10/15/2014 03:28 AM

 
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
(3-3/4)