|
( |
|
/* |
|
Copyright © 2018 Martin Geupel (http://www.racoon-artworks.de/) All Rights Reserved. |
|
|
|
Copyright © 2019 Chaos Czech a.s. (https://corona-renderer.com/) All Rights Reserved. |
|
|
|
The software is developed and maintained by Chaos Czech a.s. since 2019. Software is a component of |
|
Corona Renderer; standard End User License Agreement applies accordingly. |
|
|
|
Supported materials: |
|
— Standard / StandardMaterial |
|
— VRayMtl |
|
— VRayBlendMtl |
|
— VRayLightMtl |
|
— VRay2SidedMtl |
|
— VRayCarPaintMtl |
|
— VrayOverrideMtl |
|
— VrayMtlWrapper |
|
— VRayFastSSS (basic) |
|
— VRayFastSSS2 |
|
— VRayHairMtl |
|
— VRayColor2Bump |
|
— Arch___Design__mi |
|
— Car_Paint_Material__mi |
|
— fR_Advanced |
|
— fR_Architectural |
|
— Shellac |
|
— Autodesk_Material |
|
— Architectural |
|
— Raytrace / RaytraceMaterial (basic) |
|
— fR_Metal (basic) |
|
— fR_Glass (basic) |
|
— iray_material |
|
— CoronaLegacyMtl |
|
|
|
Supported maps: |
|
— VrayColor |
|
— VrayDirt |
|
— VrayNormalMap |
|
— VraySky |
|
— VRayCompTex |
|
— VRayEdgesTex |
|
— VRayGLSLTex |
|
— VRaySoftbox |
|
— VRayHDRI |
|
— VRayTriplanarTex |
|
— VRayColor2Bump |
|
— Normal_Bump |
|
— Autodesk_Map |
|
— Multi_Sub_Map |
|
— Ambient/Reflective_Occlusion |
|
|
|
Supported lights: |
|
— VRayLight |
|
— VRayIES |
|
— VRaySun |
|
— mr_Sun |
|
— mr_Sky_Portal (if using «Custom color source» mode) |
|
— miAreaLight |
|
— miAreaLightomni |
|
— fR RectLight |
|
— Free_Light |
|
— Target_Light |
|
— TargetDirectionallight |
|
— freeSpot |
|
— Directionallight |
|
— Omnilight |
|
— targetSpot |
|
— Daylight assemblies |
|
|
|
Other: |
|
— VrayProxy |
|
— VrayDisplacementMod |
|
|
|
To do: |
|
— VrayMultiSub map(?) |
|
— vrayEdgesTex -> corona https://corona-renderer.com/forum/index.php/topic,126.msg88521.html#msg88521 |
|
— photometric lights |
|
— Dome light conversion |
|
— Hdri white balance setting https://corona-renderer.com/forum/index.php?topic=126.msg110097#msg110097 |
|
— VrayCam to CoronaCam |
|
*/ |
|
|
|
— Note: Do not use return, break, exit and continue statements, since they are implemented using C++ |
|
— exceptions which are very slow when executed in context of MAXScript. |
|
|
|
— To measure time spent on some part of the code use the following approach: |
|
— local startTime = timeStamp() |
|
— … |
|
— <profiled code> |
|
— … |
|
— local endTime = timeStamp() |
|
— local timeSpent = endTime — startTime — Miliseconds. |
|
— format «Time spent: % msn» timeSpent |
|
|
|
global CoronaConverterSuppressGui |
|
global CoronaProxyConverter |
|
global CoronaConverter |
|
|
|
global MAX_COLOR_VALUE = 255.0 |
|
|
|
global MAPPING_TYPE_TEXTURE = 0 |
|
global MAPPING_TYPE_ENVIRONMENT = 1 |
|
|
|
global BITMAP_MAPPING_VERTEX_COLOR_CHANNEL = 1 |
|
|
|
global BITMAP_MAPPING_SPHERICAL = 0 |
|
global BITMAP_MAPPING_SCREEN = 3 |
|
|
|
global CORONA_BITMAP_MAPPING_SPHERICAL = 0 |
|
global CORONA_BITMAP_MAPPING_SCREEN = 1 |
|
|
|
— Not sure how this value was found, but it was present in the original script we got from Martin Geupel. |
|
— |
|
— Move this constant to adjustBumpValueFromVRayCommon function, once other functions which are dependent |
|
— on it would be rewritten to convert the corresponding materials to CoronaPhysicalMtl. |
|
global VRAY_BUMP_MULTIPLIER = 3.5 |
|
|
|
struct ZipMtl ( |
|
param, |
|
paramName, |
|
paramLevel, |
|
paramMap, |
|
paramMapOn, |
|
paramMapAmount |
|
) |
|
|
|
struct ProblematicMaterials ( |
|
convertedToMetal = #(), |
|
usesVolumetricScatteringButNotRefraction = #(), |
|
usesTranslucencyButNotThinShell = #(), |
|
usedRefractionColor = #() |
|
) |
|
|
|
fn openMaxScriptListener =( |
|
— 40472 is a 3ds Max’s internal action ID for opening MAXScript Listener. Found by inspecting |
|
— MAXScript Listener with MacroRecorder enabled. |
|
actionMan.executeAction 0 «40472« |
|
) |
|
|
|
— Returns index of last occurence of needle in the haystack. If the needle was not found in the haystack, |
|
— returns undefined. |
|
— haystackRange represents an index of the last element taken into account when searching the haystack. |
|
fn findLastInRange needle haystack haystackRange =( |
|
assert (needle.count >= 1) |
|
|
|
local limitedHaystack = substring haystack 1 haystackRange |
|
local index = 0 |
|
|
|
while index != undefined do ( |
|
index = findstring limitedHaystack needle |
|
|
|
if index != undefined then ( |
|
local first = index + 1 |
|
local LAST = —1 |
|
limitedHaystack = substring limitedHaystack first LAST |
|
) |
|
) |
|
|
|
if limitedHaystack.count == (amin #(haystackRange, haystack.count)) then ( |
|
/*return*/ undefined |
|
) else ( |
|
/*return*/ haystackRange — limitedHaystack.count |
|
) |
|
) |
|
|
|
fn wrapText inputText maxLineLength =( |
|
local wrappedText = «« |
|
local index = 0 |
|
|
|
while (index != undefined) and (inputText.count > maxLineLength) do ( |
|
local WHITESPACE = « « |
|
index = findLastInRange WHITESPACE inputText maxLineLength |
|
|
|
if index != undefined then ( |
|
wrappedText += substring inputText 1 index |
|
wrappedText += «n« |
|
local first = index + 1 |
|
local LAST = —1 |
|
inputText = substring inputText first LAST |
|
) |
|
) |
|
wrappedText += inputText |
|
|
|
/*return*/ wrappedText |
|
) |
|
|
|
— Print conversion warnings to MAXScript Listener. |
|
fn printConversionWarnings problematicMtls =( |
|
openMaxScriptListener() |
|
|
|
local MAX_LINE_LENGTH = 110 |
|
|
|
if problematicMtls.convertedToMetal.count > 0 or problematicMtls.usesVolumetricScatteringButNotRefraction.count > 0 or problematicMtls.usesTranslucencyButNotThinShell.count > 0 or problematicMtls.usedRefractionColor.count > 0 then ( |
|
local INDENTATION = « « |
|
|
|
if problematicMtls.convertedToMetal.count > 0 then ( |
|
local WARNING = «Warning: The following materials were converted to CoronaPhysicalMtl as « |
|
WARNING += «metals. It is advised to check their correctness:nn« |
|
|
|
format (wrapText WARNING MAX_LINE_LENGTH) |
|
|
|
for materialName in problematicMtls.convertedToMetal do ( |
|
format «%- %n« INDENTATION materialName |
|
) |
|
format «n« |
|
) |
|
|
|
if problematicMtls.usesVolumetricScatteringButNotRefraction.count > 0 then ( |
|
local WARNING = «Warning: The following materials are defined with non-zero volumetric « |
|
WARNING += «scattering distance parameter but are not refractive. As a result the volumetric « |
|
WARNING += «scattering has no effect. If such effect is desired, make the materials « |
|
WARNING += «refractive:nn« |
|
|
|
format (wrapText WARNING MAX_LINE_LENGTH) |
|
|
|
for materialName in problematicMtls.usesVolumetricScatteringButNotRefraction do ( |
|
format «%- %n« INDENTATION materialName |
|
) |
|
format «n« |
|
) |
|
|
|
if problematicMtls.usesTranslucencyButNotThinShell.count > 0 then ( |
|
local WARNING = «Warning: The following materials are defined with non-zero translucency « |
|
WARNING += «parameter but do not have «Thin shell« parameter enabled. As a result the « |
|
WARNING += «translucency has no effect. If such effect is desired, enable the «Thin shell« « |
|
WARNING += «parameter:nn« |
|
|
|
format (wrapText WARNING MAX_LINE_LENGTH) |
|
|
|
for materialName in problematicMtls.usesTranslucencyButNotThinShell do ( |
|
format «%- %n« INDENTATION materialName |
|
) |
|
format «n« |
|
) |
|
|
|
if problematicMtls.usedRefractionColor.count > 0 then ( |
|
local WARNING = «Warning: The following materials used refraction color parameter and / or « |
|
WARNING += «map, however CoronaPhysicalMtl does not provide such parameter. To achieve an « |
|
WARNING += «effect of colored refractions use volumetric absorption parameters instead. « |
|
WARNING += «Corona Converter tried to affect volumetric absorption color parameter of the « |
|
WARNING += «converted material by the original refraction color parameter, however this « |
|
WARNING += «mapping may not produce exactly the same results and some manual intervention « |
|
WARNING += «might be necessary:nn« |
|
|
|
format (wrapText WARNING MAX_LINE_LENGTH) |
|
|
|
for materialName in problematicMtls.usedRefractionColor do ( |
|
format «%- %n« INDENTATION materialName |
|
) |
|
format «n« |
|
) |
|
) |
|
|
|
local NOTE = «Note: While Corona Converter tries to preserve look and characteristics of the « |
|
NOTE += «original materials as much as possible, in some cases there is no way to accurately map « |
|
NOTE += «all the parameters of the original materials to native Corona materials which may « |
|
NOTE += «result in some visual differences. Therefore it is advised to check the converted « |
|
NOTE += «materials once the conversion is finished.nn« |
|
|
|
format (wrapText NOTE MAX_LINE_LENGTH) |
|
) |
|
|
|
— Checks the input material for common problems which occur during conversion to CoronaPhysicalMtl and |
|
— writes them to the &problematicMtls. |
|
fn checkCommonConversionProblems coronaPhysicalMat &problematicMtls =( |
|
assert ((classof coronaPhysicalMat) == CoronaPhysicalMtl) |
|
|
|
if coronaPhysicalMat.metalnessMode == 1 then ( |
|
append problematicMtls.convertedToMetal coronaPhysicalMat.name |
|
) |
|
if coronaPhysicalMat.attenuationDistance > 0 and coronaPhysicalMat.refractionAmount == 0 then ( |
|
append problematicMtls.usesVolumetricScatteringButNotRefraction coronaPhysicalMat.name |
|
) |
|
if coronaPhysicalMat.translucencyFraction > 0 and not coronaPhysicalMat.useThinMode then ( |
|
append problematicMtls.usesTranslucencyButNotThinShell coronaPhysicalMat.name |
|
) |
|
) |
|
|
|
fn round numericValue =( |
|
/*return*/ floor (numericValue + 0.5) |
|
) |
|
|
|
— If the number or color values are floating point values then this function performs approximative |
|
— comparison, otherwise a typical (strict) comparison is performed. |
|
— |
|
— Both input values are expected to be the same type (checked by an assert). |
|
fn approxEq numberOrColor0 numberOrColor1 epsilon:1e—6 =( |
|
if ((classof numberOrColor0) == integer) or ((classof numberOrColor0) == float) then ( |
|
assert ((classof numberOrColor1) == integer or (classof numberOrColor1) == float) |
|
) |
|
|
|
if ((classof numberOrColor0) == float) or ((classof numberOrColor1) == float) then ( |
|
/*return*/ abs (numberOrColor0 — numberOrColor1) <= epsilon |
|
) else ( |
|
assert ((classof numberOrColor0) == (classof numberOrColor1)) |
|
|
|
if (classof numberOrColor0 == integer) then ( |
|
/*return*/ numberOrColor0 == numberOrColor1 |
|
) else ( |
|
assert ((classof numberOrColor0) == color) |
|
|
|
— Round all the components and cast them to int, since they are presented to user as ints, |
|
— however they are internally represented as floats, which may lead to inaccurate |
|
— comparisons. |
|
local r0 = int(round numberOrColor0.r) |
|
local g0 = int(round numberOrColor0.g) |
|
local b0 = int(round numberOrColor0.b) |
|
|
|
local r1 = int(round numberOrColor1.r) |
|
local g1 = int(round numberOrColor1.g) |
|
local b1 = int(round numberOrColor1.b) |
|
|
|
/*return*/ (r0 == r1) and (g0 == g1) and (b0 == b1) |
|
) |
|
) |
|
) |
|
|
|
— Converts color with values in range [0, 255] to its average luminance in range [0, 255]. |
|
fn colorToAverageLuminance inputColor =( |
|
/*return*/ ((inputColor.r + inputColor.g + inputColor.b) as float) / 3.0 |
|
) |
|
|
|
— Indicates whether the input map represents a normal map. |
|
fn isNormalMap inputMap =( |
|
local inputMapClass = classof inputMap |
|
/*return*/ inputMapClass == VrayNormalMap or inputMapClass == CoronaNormal or inputMapClass == Normal_Bump |
|
) |
|
|
|
fn adjustBumpValueFromVRayCommon &inputMaterial textureParameterName textureAmountName =( |
|
assert ((classof inputMaterial) == CoronaPhysicalMtl) |
|
|
|
local bumpTexture = getProperty inputMaterial textureParameterName |
|
local bumpAmount = getProperty inputMaterial textureAmountName |
|
|
|
if bumpTexture != undefined then ( |
|
— This heuristic was used in the original script we got from Martin Geupel. |
|
if (not (isNormalMap bumpTexture)) then ( |
|
bumpAmount = bumpAmount * VRAY_BUMP_MULTIPLIER |
|
) |
|
) |
|
|
|
setProperty &inputMaterial textureAmountName bumpAmount |
|
) |
|
|
|
— If the inputMaterial was created by conversion from any V-Ray material and uses bump (not normal) |
|
— mapping, its bump value should be adjusted by a magic constant to preserve similar look. |
|
fn adjustBaseBumpValueFromVRay &inputMaterial =( |
|
/*return*/ adjustBumpValueFromVRayCommon &inputMaterial «baseBumpTexmap« «baseBumpMapAmount« |
|
) |
|
|
|
— If the inputMaterial was created by conversion from any V-Ray material and uses clearcoat bump (not |
|
— normal) mapping, its clearcoat bump value should be adjusted by a magic constant to preserve similar |
|
— look. |
|
fn adjustClearcoatBumpValueFromVRay &inputMaterial =( |
|
/*return*/ adjustBumpValueFromVRayCommon &inputMaterial «clearcoatBumpTexmap« «clearcoatBumpMapAmount« |
|
) |
|
|
|
fn convertVRayDisplacementModToCoronaDisplacementMod inputMod =( |
|
assert ((classof inputMod) == VRayDisplacementMod) |
|
|
|
outputMod = CoronaDisplacementMod() |
|
outputMod.mapSource = 1 |
|
outputMod.texmap = inputMod.texmap |
|
|
|
outputMod.levelMin = inputMod.shift |
|
outputMod.levelMax = inputMod.shift + inputMod.amount |
|
|
|
outputMod.useWaterLevel = inputMod.waterLevelOn |
|
outputMod.waterLevel = (inputMod.waterLevelValue — inputMod.shift) / inputMod.amount |
|
|
|
/*return*/ outputMod |
|
) |
|
|
|
— Based on: https://forums.cgsociety.org/t/check-if-vray-is-installed/1039059 |
|
fn isVRayInstalled =( |
|
/*return*/ vray != undefined |
|
) |
|
|
|
fn convertAllVRayDisplacementModsToCoronaDisplacementMods =( |
|
if isVRayInstalled() then ( |
|
local allMods = (getclassinstances VRayDisplacementMod) |
|
for dsplMod in allMods where (classof dsplMod == VRayDisplacementMod) do ( |
|
replaceInstances dsplMod (convertVRayDisplacementModToCoronaDisplacementMod dsplMod) |
|
) |
|
) else ( |
|
— If V-Ray is not installed, the VRayDisplacementMod class is not available in MAXScript. If we |
|
— used it anyway, MAXScript would encounter a runtime error. |
|
local MESSAGE = «This function requires V-Ray renderer to be installed in 3ds Max.« |
|
messageBox MESSAGE title:«Warning« |
|
) |
|
) |
|
|
|
fn usesDisplacementCoronaPhysicalMtl inputMaterial =( |
|
assert ((classof inputMaterial) == CoronaPhysicalMtl) |
|
|
|
local displacementHeight = inputMaterial.displacementMaximum — inputMaterial.displacementMinimum |
|
|
|
if displacementHeight > 0.0 then ( |
|
— CoronaPhysicalMtl does not have a «displacement map amount» parameter. |
|
/*return*/ inputMaterial.displacementTexmap != undefined and inputMaterial.displacementTexmapOn |
|
) else ( |
|
/*return*/ false |
|
) |
|
) |
|
|
|
fn lerp value1 value2 bias =( |
|
assert ((0.0 <= bias) and (bias <= 1.0)) |
|
|
|
/*return*/ (1.0 — bias) * value1 + bias * value2 |
|
) |
|
|
|
fn addCoronaColorCorrectNode colorCorrectNodeName inputTexture factor:1.0 gamma:1.0 saturation:0.0 =( |
|
assert ((0.0 <= factor) and (factor <= 1.0)) |
|
assert ((—1.0 <= saturation) and (saturation <= 1.0)) |
|
|
|
local colorCorrectNode = CoronaColorCorrect() |
|
colorCorrectNode.inputTexmap = inputTexture |
|
colorCorrectNode.name = colorCorrectNodeName |
|
local channelValue = factor * MAX_COLOR_VALUE |
|
colorCorrectNode.tint = (color channelValue channelValue channelValue) |
|
colorCorrectNode.gamma = gamma |
|
colorCorrectNode.saturation = saturation |
|
|
|
/*return*/ colorCorrectNode |
|
) |
|
|
|
fn mapIsActive map mapEnabled mapContribution =( |
|
/*return*/ map != undefined and mapEnabled and mapContribution > 0.0 |
|
) |
|
|
|
fn usesLobeCoronaMtl paramLevel paramTexmap paramTexmapOn paramMapAmount paramColor =( |
|
if paramLevel > 0.0 then ( |
|
if mapIsActive paramTexmap paramTexmapOn paramMapAmount then ( |
|
/*return*/ true |
|
) else ( |
|
/*return*/ paramColor != black |
|
) |
|
) else ( |
|
/*return*/ false |
|
) |
|
) |
|
|
|
— If the inputNode or any of its upstream nodes (assuming that the upstream nodes are connected via |
|
— CoronaMix nodes) is a Falloff map and use Fresnel mode, its «Override Material IOR» parameter is |
|
— enabled and its value is set to iorValue. |
|
— |
|
— This function is needed because of the following situation: Falloff maps in 3ds Max can use material’s |
|
— IoR as its input value. In most cases this behavior does not cause any issues, however when such map is |
|
— connected either directly or as a part of some shading network to IoR parameter of some material, it |
|
— could cause infinite loop leading to stack overflow. |
|
fn setFixedIorValueForFalloffMaps inputTexture iorValue =( |
|
if ((classof inputTexture) == CoronaMix) then ( |
|
setFixedIorValueForFalloffMaps inputTexture.texmapTop iorValue |
|
setFixedIorValueForFalloffMaps inputTexture.texmapBottom iorValue |
|
setFixedIorValueForFalloffMaps inputTexture.texmapMix iorValue |
|
) else if ((classof inputTexture) == Falloff) then ( |
|
local FRESNEL_MODE = 2 |
|
if (inputTexture.type == FRESNEL_MODE) and (inputTexture.mtlIOROverride == false) then ( |
|
inputTexture.mtlIOROverride = true |
|
inputTexture.ior = iorValue |
|
) |
|
) |
|
) |
|
|
|
fn usesTranslucencyCoronaPhysicalMtl inputMaterial =( |
|
assert ((classof inputMaterial) == CoronaPhysicalMtl) |
|
/*return*/ usesLobeCoronaMtl inputMaterial.translucencyFraction inputMaterial.translucencyFractionTexmap inputMaterial.translucencyFractionTexmapOn inputMaterial.translucencyFractionMapAmount inputMaterial.translucencyColor |
|
) |
|
|
|
fn usesRefractionCoronaPhysicalMtl inputMaterial =( |
|
assert ((classof inputMaterial) == CoronaPhysicalMtl) |
|
/*return*/ usesLobeCoronaMtl inputMaterial.refractionAmount inputMaterial.refractionAmountTexmap inputMaterial.refractionAmountTexmapOn inputMaterial.refractionAmountMapAmount inputMaterial.thinAbsorptionColor |
|
) |
|
|
|
fn usesSelfIlluminationCoronaPhysicalMtl inputMaterial =( |
|
assert ((classof inputMaterial) == CoronaPhysicalMtl) |
|
/*return*/ usesLobeCoronaMtl inputMaterial.selfIllumLevel inputMaterial.selfIllumTexmap inputMaterial.selfIllumTexmapOn inputMaterial.selfillumMapAmount inputMaterial.selfIllumColor |
|
) |
|
|
|
— Creates a default CoronaPhysicalMtl. |
|
fn createDefaultCoronaPhysicalMtl materialName =( |
|
local outputMaterial = CoronaPhysicalMtl() |
|
outputMaterial.name = materialName |
|
|
|
/*return*/ outputMaterial |
|
) |
|
|
|
struct CoronaProxyConverterStr ( |
|
vrayMeshReader, |
|
proxyInfoArray = #(), |
|
proxyFileArray = #(), |
|
|
|
VrayProxyInfo =( |
|
struct VrayProxyInfo ( |
|
maxobj, |
|
proxyFile, |
|
displayType, |
|
playbackOffset, |
|
playbackSpeed, |
|
proxyScale |
|
) |
|
), |
|
|
|
VrayProxyFile =( |
|
struct VrayProxyFile ( |
|
filename, |
|
doesExist = true, |
|
owner, |
|
frameCount = 1, |
|
coronaProxyFilename = undefined, |
|
|
|
on create do ( |
|
if (doesFileExist filename) then ( |
|
frameCount = owner.vrayMeshReader.GetNumberOfFrames filename |
|
) else ( |
|
doesExist = false |
|
) |
|
append owner.proxyFileArray this |
|
) |
|
) |
|
), |
|
|
|
fn combineToPath stringArray =( |
|
local outPath = «« |
|
|
|
for pth in stringArray do ( |
|
outPath = pathConfig.appendPath outPath pth |
|
) |
|
outPath |
|
), |
|
|
|
fn maxAnimRange =( |
|
local proxyLengthArray = for i in proxyFileArray collect i.frameCount |
|
|
|
if proxyLengthArray.count != 0 then ( |
|
sort proxyLengthArray |
|
proxyLengthArray[proxyLengthArray.count] |
|
) else ( |
|
1 |
|
) |
|
), |
|
|
|
fn isProxyFileDefined filename =( |
|
local found = false |
|
local out = undefined |
|
|
|
for prx in proxyFileArray while not found do ( |
|
if prx.filename == filename then ( |
|
out = prx |
|
found = true |
|
) |
|
) |
|
out |
|
), |
|
|
|
fn VrayMeshReaderAssembly =( |
|
— file:///C:/Program%20Files/Chaos%20Group/V-Ray/3dsmax%202016%20for%20×64/docs/vrmesh_format.html |
|
source = «« |
|
source += «using System;n« |
|
source += «using System.IO;n« |
|
source += «n« |
|
source += «public class vrMeshReadern« |
|
source += «{n« |
|
source += « public int GetNumberOfFrames(string filePath)n« |
|
source += « {n« |
|
source += « byte[] buffer = null;n« |
|
source += « int FrameCount = 0;n« |
|
source += « n« |
|
source += « FileStream vrM = new FileStream(filePath, FileMode.Open);n« |
|
source += « tryn« |
|
source += « {n« |
|
source += « vrM.Seek(11, SeekOrigin.Begin); // skipping fileversion and descriptionn« |
|
source += « n« |
|
source += « UInt64 lutOffset;n« |
|
source += « buffer = new byte[8];n« |
|
source += « vrM.Read(buffer, 0, buffer.Length);n« |
|
source += « lutOffset = BitConverter.ToUInt64(buffer, 0);n« |
|
source += « n« |
|
source += « vrM.Seek((long)lutOffset, SeekOrigin.Begin);n« |
|
source += « n« |
|
source += « buffer = new byte[4];n« |
|
source += « vrM.Read(buffer, 0, buffer.Length);n« |
|
source += « UInt32 numVoxels = (BitConverter.ToUInt32(buffer, 0));n« |
|
source += « vrM.Seek(36 * numVoxels, SeekOrigin.Current);n« |
|
source += « FrameCount = 1;n« |
|
source += « n« |
|
source += « while (numVoxels != 0)n« |
|
source += « {n« |
|
source += « buffer = new byte[4];n« |
|
source += « vrM.Read(buffer, 0, buffer.Length);n« |
|
source += « numVoxels = (BitConverter.ToUInt32(buffer, 0));n« |
|
source += « if (numVoxels == 0) { break; }n« |
|
source += « FrameCount++;n« |
|
source += « vrM.Seek(36 * numVoxels, SeekOrigin.Current);n« |
|
source += « }n« |
|
source += « vrM.Close();n« |
|
source += « }n« |
|
source += « catch (Exception)n« |
|
source += « {n« |
|
source += « vrM.Close();n« |
|
source += « throw;n« |
|
source += « }n« |
|
source += « return FrameCount;n« |
|
source += « }n« |
|
source += «}n« |
|
|
|
csharpProvider = dotnetobject «Microsoft.CSharp.CSharpCodeProvider« |
|
compilerParams = dotnetobject «System.CodeDom.Compiler.CompilerParameters« |
|
|
|
compilerParams.ReferencedAssemblies.Add «System.dll« |
|
|
|
compilerParams.GenerateInMemory = on |
|
compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source) |
|
|
|
(compilerResults.CompiledAssembly).CreateInstance «vrMeshReader« |
|
), |
|
|
|
fn collectSceneData =( |
|
for prx in (getClassInstances VrayProxy) do ( |
|
local prxInfo = VrayProxyInfo() |
|
prxInfo.maxobj = prx |
|
|
|
local proxyFile = isProxyFileDefined prx.fileName |
|
prxInfo.proxyFile = if proxyFile != undefined then ( |
|
proxyFile |
|
) else ( |
|
VrayProxyFile filename:prx.fileName owner:this |
|
) |
|
prxInfo.displayType = prx.display |
|
prxInfo.playbackOffset = prx.anim_offset |
|
prxInfo.playbackSpeed = prx.anim_speed |
|
prxInfo.proxyScale = prx.proxy_scale |
|
|
|
append proxyInfoArray prxInfo |
|
) |
|
), |
|
|
|
fn generateCoronaProxies location: overwrite: =( |
|
local askForOverwrite = true |
|
local overwriteFiles = false |
|
|
|
if overwrite != unsupplied then ( |
|
askForOverwrite = false |
|
overwriteFiles = overwrite |
|
) |
|
|
|
for prx in proxyFileArray do ( |
|
local vrProxy = vrayProxy fileName:prx.Filename display:4 proxy_scale:1.0 — whole mesh display |
|
local corProxy = CProxy() |
|
local outpath |
|
local skipFile = false |
|
|
|
if location == unsupplied then ( |
|
outpath = combineToPath #((getFilenamePath prx.Filename), (getFilenameFile prx.Filename) + «.cgeo«) |
|
) else ( |
|
outpath = combineToPath #(location, (getFilenameFile prx.Filename) + «.cgeo«) |
|
) |
|
prx.coronaProxyFilename = outpath |
|
|
|
if doesFileExist outpath then ( |
|
if askForOverwrite then ( |
|
overwriteFiles = queryBox «One or more CoronaProxy files do already exist on Disk, do you want to overwrite them?nn(If you press «No«, the existing files will be used for the generated Proxies)« title:«Corona Proxy Export« |
|
askForOverwrite = false |
|
) |
|
|
|
if not overwriteFiles then ( |
|
skipFile = true |
|
) |
|
) |
|
|
|
if prx.doesExist then ( |
|
if ((getPolygonCount vrProxy)[1] == 0) then ( — If polygon count is 0 then 3ds Max crashes — this is a Corona bug. |
|
skipFile = true |
|
prx.coronaProxyFilename = undefined |
|
format («Skipped [.vrmesh contains 0 faces]: « + prx.Filename + «n«) |
|
) |
|
) else ( — If VRMesh file path is invalid. |
|
skipFile = true |
|
prx.coronaProxyFilename = undefined |
|
format («Skipped [invalid .vrmesh filepath]: « + prx.Filename + «n«) |
|
) |
|
|
|
if not skipFile then ( |
|
with redraw off ( |
|
if prx.frameCount == 1 then ( — Single frame. |
|
CProxy.ProxyFp.fromScene corProxy vrProxy outpath |
|
) else ( — Animated. |
|
CProxy.ProxyFp.fromSceneAnimated corProxy vrProxy outpath 0 (prx.frameCount — 1) 10000 1 |
|
) |
|
) |
|
format («Generated CoronaProxy: « + outpath + «n«) |
|
) |
|
|
|
delete vrProxy |
|
delete corProxy |
|
gc light:true |
|
) |
|
), |
|
|
|
fn replaceVrayProxies =( |
|
for vrayPrx in proxyInfoArray where classof vrayPrx.maxobj == VRayProxy do ( |
|
cProxFilename = vrayPrx.proxyFile.coronaProxyFilename |
|
if cProxFilename != undefined then ( |
|
crnProxy = CProxy filename:cProxFilename animationOffset:vrayPrx.playbackOffset animationSpeedMultiplier:vrayPrx.playbackSpeed previzType:2 |
|
|
|
replaceInstances vrayPrx.maxobj crnProxy |
|
|
|
if vrayPrx.proxyScale != 1.0 then ( |
|
local prxInstances |
|
InstanceMgr.GetInstances crnProxy &prxInstances |
|
|
|
for obj in prxInstances do ( |
|
obj.scale *= vrayPrx.proxyScale |
|
) |
|
) |
|
delete crnProxy |
|
) |
|
) |
|
|
|
gc light:true |
|
), |
|
|
|
fn convertProxies location: overwrite: =( |
|
local saveStart = animationRange.start |
|
local saveEnd = animationRange.end |
|
|
|
collectSceneData() |
|
|
|
animationRange = (interval 0 (maxAnimRange())) |
|
|
|
generateCoronaProxies location:location overwrite:overwrite |
|
replaceVrayProxies() |
|
|
|
proxyInfoArray = #() |
|
proxyFileArray = #() |
|
animationRange = (interval saveStart saveEnd) |
|
), |
|
|
|
CoronaProxyConverterRoll = rollout CoronaProxyConverterRoll «Corona Proxy conversion« width:230 height:170 ( |
|
local owner = if owner != undefined do ( |
|
owner |
|
) |
|
local savePath = undefined |
|
|
|
group «Options« ( |
|
label lbl «Location for created Corona Proxies« align:#left |
|
radiobuttons rdoMode «« labels:#(«Same file path as original«, «Pick new path«) columns:1 align:#left |
|
button btnPick «Pick save path« width:200 enabled:false |
|
) |
|
group «Convert« ( |
|
button btnConvertProxies «Convert Proxies« width:200 height:32 |
|
) |
|
|
|
on btnPick pressed do ( |
|
|
|
savePath = getSavePath() |
|
if savePath != undefined do ( |
|
btnPick.caption = savePath |
|
btnPick.tooltip = savePath |
|
) |
|
) |
|
|
|
on rdoMode changed state do ( |
|
if state == 1 then ( |
|
btnPick.enabled = false |
|
) else ( |
|
btnPick.enabled = true |
|
) |
|
) |
|
|
|
on btnConvertProxies pressed do ( |
|
with animate off ( |
|
if rdoMode.state == 1 then ( |
|
owner.convertProxies() |
|
) else ( |
|
if savePath != undefined then ( |
|
owner.convertProxies location:savePath |
|
) else ( |
|
messagebox «Invalid save Path!« title:«Error« |
|
) |
|
) |
|
) |
|
) |
|
), |
|
|
|
fn openGui =( |
|
createDialog CoronaProxyConverterRoll style:#(#style_titlebar, #style_sysmenu, #style_minimizebox) |
|
), |
|
|
|
fn destroyGui =( |
|
try ( |
|
destroyDialog CoronaProxyConverterRoll |
|
) catch () |
|
), |
|
|
|
on create do ( |
|
CoronaProxyConverterRoll.owner = this |
|
vrayMeshReader = VrayMeshReaderAssembly() |
|
) |
|
) |
|
|
|
struct CoronaConverterStr ( |
|
CoronaConverterVersion = «2.02«, |
|
|
|
converterSettings =( |
|
struct converterSettings ( |
|
— Try to not remove / rename the variables and functions which are described here: |
|
— https://www.racoon-artworks.de/CoronaConverter/mxsDocumentation.html if possible, to |
|
— prevent breakage of the legacy MAXScript API (which we never officially promised to |
|
— maintain / keep stable), however some of our long-term customers still use it. |
|
VrayHDRIToBitmaptexture = true, |
|
translucencyEnablesThinShell = true, |
|
bitmapTextureToCoronaBitmap = false, |
|
addCoronaPrefix = false, |
|
userPrefixStr = «CRN.«, |
|
convertVrayProxies = true, |
|
switchRenderEngine = true, |
|
ignoreLegacyMaterials = true, |
|
miLightsToCrnLights = false, |
|
showWarnings = true, |
|
printInfo = true, |
|
silent = false, |
|
useTryCatchBugReporting = true, |
|
UI_LINK_COLOR = (if (colorMan.getColor #background).x < 0.5 then ( — Colors for dark / light UI. |
|
color 150 180 210 |
|
) else ( |
|
color 0 80 200 |
|
)), |
|
EXPOSE_DEBUG_SETTINGS = false, |
|
|
|
dialogPosX = 0, |
|
dialogPosY = 0, |
|
INI_PATH = «$plugcfg\CoronaConverter.ini«, |
|
|
|
VRAY_DIRECTIONALITY_TO_CORONA_DIRECTIONALITY = #([1.0,1.0],[0.99,0.96],[0.98,0.88],[0.97,0.82],[0.96,0.78],[0.95,0.74],[0.94,0.72], |
|
[0.93,0.69],[0.92,0.68],[0.91,0.66],[0.9,0.65],[0.89,0.63],[0.88,0.62],[0.87,0.61],[0.86,0.6],[0.85,0.6],[0.84,0.59], |
|
[0.83,0.58],[0.82,0.57],[0.81,0.57],[0.8,0.56],[0.79,0.56],[0.78,0.55],[0.77,0.55],[0.76,0.54],[0.75,0.54],[0.74,0.53], |
|
[0.73,0.53],[0.72,0.52],[0.71,0.52],[0.7,0.51],[0.69,0.51],[0.68,0.51],[0.67,0.5],[0.66,0.5],[0.65,0.5],[0.64,0.49], |
|
[0.63,0.49],[0.62,0.49],[0.61,0.49],[0.6,0.48],[0.59,0.48],[0.58,0.48],[0.57,0.47],[0.56,0.47],[0.55,0.47],[0.54,0.47], |
|
[0.53,0.46],[0.52,0.46],[0.51,0.46],[0.5,0.46],[0.49,0.45],[0.48,0.45],[0.47,0.45],[0.46,0.45],[0.45,0.44],[0.44,0.44], |
|
[0.43,0.44],[0.42,0.44],[0.41,0.44],[0.4,0.43],[0.39,0.43],[0.38,0.43],[0.37,0.43],[0.36,0.42],[0.35,0.42],[0.34,0.42], |
|
[0.33,0.42],[0.32,0.41],[0.31,0.41],[0.3,0.41],[0.29,0.41],[0.28,0.41],[0.27,0.4],[0.26,0.4],[0.25,0.4],[0.24,0.4], |
|
[0.23,0.4],[0.22,0.39],[0.21,0.39],[0.2,0.39],[0.19,0.38],[0.18,0.38],[0.17,0.38],[0.16,0.38],[0.15,0.37],[0.14,0.37], |
|
[0.13,0.37],[0.12,0.36],[0.11,0.36],[0.1,0.36],[0.09,0.35],[0.08,0.35],[0.07,0.35],[0.06,0.34],[0.05,0.33],[0.04,0.33], |
|
[0.03,0.32],[0.02,0.31],[0.01,0.3],[0.0,0.0]) |
|
) |
|
converterSettings() |
|
), |
|
|
|
converterTempData =( |
|
struct converterTempData ( |
|
owner, |
|
— Used to determine which classes will be converted. |
|
supportedMtlClassNames = #(«StandardMaterial«, «VRayMtl«, «VRayBlendMtl«, «VRayLightMtl«, «VRay2SidedMtl«, «VRayCarPaintMtl«, «VrayOverrideMtl«, «VrayMtlWrapper«, «Arch___Design__mi«, «Car_Paint_Material__mi«, «fR_Advanced«, «fR_Architectural« , «Shellac«, «Autodesk_Material«, «VRayFastSSS«, «VRayFastSSS2«, «VRayHairMtl«, «VRaySkinMtl«, «RaytraceMaterial«, «Architectural«, «fR_Metal«, «fR_Glass«, «iray_Material«, «VRayBumpMtl«, «CoronaLegacyMtl«), |
|
supportedMapClassNames = #(«Bitmaptexture«, «VrayColor«, «VrayDirt«, «Normal_Bump«, «VrayNormalMap«, «VraySky«, «VRayCompTex«, «VRayEdgesTex«, «VRayGLSLTex«, «VRaySoftbox«, «Autodesk_Map«, «Ambient_Reflective_Occlusion__3dsmax«, «Multi_Sub_Map«, «VRayHDRI«, «VRayTriplanarTex«, «VRayColor2Bump«), |
|
— NOT used to determine which classes will be converted, just for information purposes. |
|
supportedLightClassNames = #(«VRayLight«, «VRaySun«, «mrSun«, «mr_Sky_Portal«, «VRayIES«, «miAreaLight«, «miAreaLightomni«, «RectLight«, «Free_Light«, «Target_Light«, «TargetDirectionallight«, «freeSpot«, «Directionallight«, «Omnilight«, «targetSpot«, «Daylight Assemblies«), |
|
|
|
—glossyConversionOutputMap = undefined, |
|
glossyConversionOutputMapVrayBlinnCoronaClGgx = undefined, |
|
glossyConversionOutputMapVrayGgxCoronaClGgx = undefined, |
|
AD_mats_found = false, |
|
|
|
originalMaterials = #(), |
|
newMaterials = #(), |
|
originalMaps = #(), |
|
newMaps = #(), |
|
orig_lights= #(), |
|
new_lights= #(), |
|
|
|
foundAdskMtls = #(), |
|
errorBuffer = #() |
|
) |
|
converterTempData owner:this |
|
), |
|
|
|
converterTools =( |
|
struct converterTools ( |
|
owner, |
|
|
|
private fn collectMaterialClasses =( |
|
local materialClassNames = «« as stringstream |
|
— Writes names of all available material classes to the materialClassNames variable. |
|
showclass «*:material*« to:materialClassNames |
|
|
|
— Note that filterstring() function treats every single character of the separator string |
|
— parameter as an individual separator. |
|
|
|
— Split string materialClassNames to an array of strings. |
|
local SEPARATOR = «n« |
|
local materialClassNames = filterstring (materialClassNames as string) SEPARATOR |
|
|
|
— Filter out only «raw» material class names. |
|
local materialClassNames = for materialClassName in materialClassNames collect ( |
|
local SEPARATOR = «:« |
|
local materialClassName = (filterstring materialClassName SEPARATOR)[1] |
|
|
|
local bracketIndex = findString materialClassName «(« |
|
|
|
if bracketIndex == undefined then ( |
|
materialClassName |
|
) else ( |
|
— Text in the brackets contains human-readable class names which we want to |
|
— filter out (including the bracket symbols), i.e. we only want «raw» class |
|
— names. |
|
substring materialClassName 1 (bracketIndex — 1) |
|
) |
|
) |
|
|
|
— Use alphabetical ordering. |
|
sort materialClassNames |
|
|
|
/*return*/ materialClassNames |
|
), |
|
|
|
private fn recursiveShowMaps orig_mtl mode =( |
|
local sub_count = getNumSubMtls orig_mtl |
|
if sub_count >= 1 then ( |
|
for i = 1 to sub_count do ( |
|
submtl = getSubMtl orig_mtl i |
|
if submtl != undefined do ( |
|
recursiveShowMaps submtl mode |
|
) |
|
) |
|
) else ( |
|
— Remove support for CoronaLegacyMtl in the future, once we completely deprecate it. |
|
if (classof orig_mtl == CoronaPhysicalMtl) or (classof orig_mtl == CoronaLegacyMtl) then ( |
|
try ( |
|
showTextureMap orig_mtl mode |
|
) catch () |
|
) |
|
) |
|
), |
|
|
|
public |
|
CoronaMtlConvStatsRoll = rollout CoronaMtlConvStatsRoll «Corona materials statistics« width:250 height:160 ( |
|
local TEXT_WIDTH = 240 |
|
label lblNumCrnMat «Number of CoronaPhysicalMtl(s): « pos:[8, 8] width:TEXT_WIDTH height:16 |
|
label lblNumRefract «Refraction:« pos:[16, 24] width:TEXT_WIDTH height:16 |
|
label lblNumSelfIllu «Self illumination:« pos:[16, 40] width:TEXT_WIDTH height:16 |
|
label lblNumTransl «Translucency:« pos:[16, 56] width:TEXT_WIDTH height:16 |
|
label lblNumOpacity «Opacity:« pos:[16, 72] width:TEXT_WIDTH height:16 |
|
label lblNumDisplace «Displacement:« pos:[16, 88] width:TEXT_WIDTH height:16 |
|
label lblNumCrnLight «Number of CoronaLightMtls: « pos:[8, 112] width:TEXT_WIDTH height:16 |
|
label lblNumEmitting «Emitting light (Direct):« pos:[16, 128] width:TEXT_WIDTH height:16 |
|
|
|
on CoronaMtlConvStatsRoll open do ( |
|
local CrnMats = getclassinstances CoronaPhysicalMtl |
|
local numTwoSided = 0 |
|
local numCaustics = 0 |
|
local numRefractiveCrn = 0 |
|
local numSelfIlluCrn = 0 |
|
local numTranslucentCrn = 0 |
|
local numOpacityCrn = 0 |
|
local numDisplacementCrn = 0 |
|
|
|
for mat in CrnMats do ( |
|
if (usesRefractionCoronaPhysicalMtl mat) then ( |
|
numRefractiveCrn += 1 |
|
) |
|
|
|
if mat.useThinMode then ( |
|
numTwoSided += 1 |
|
) |
|
|
|
if mat.useCaustics then ( |
|
numCaustics += 1 |
|
) |
|
|
|
if (usesSelfIlluminationCoronaPhysicalMtl mat) then ( |
|
numSelfIlluCrn += 1 |
|
) |
|
|
|
if (usesTranslucencyCoronaPhysicalMtl mat) then ( |
|
numTranslucentCrn += 1 |
|
) |
|
|
|
if mat.opacityLevel < 1.0 then ( |
|
if mapIsActive mat.opacityTexmap mat.opacityTexmapOn mat.opacityMapAmount then ( |
|
numOpacityCrn += 1 |
|
) else if mat.opacityColor != white then ( |
|
numOpacityCrn += 1 |
|
) |
|
) |
|
|
|
if (usesDisplacementCoronaPhysicalMtl mat) then ( |
|
numDisplacementCrn += 1 |
|
) |
|
) |
|
|
|
local CrnLightMat = getclassinstances CoronaLightMtl |
|
local numEmittingLightMat = 0 |
|
|
|
for mat in CrnLightMat do ( |
|
if mat.emitLight then ( |
|
numEmittingLightMat += 1 |
|
) |
|
) |
|
|
|
lblNumCrnMat.text = «Number of CoronaPhysicalMtl(s): « + CrnMats.count as string |
|
lblNumRefract.text = «Refraction: « + numRefractiveCrn as string + « (Caustics: « + numCaustics as string + «, Thin shell: « + numTwoSided as string + «)« |
|
lblNumSelfIllu.text = «Self illumination: « + numSelfIlluCrn as string |
|
lblNumTransl.text = «Translucency: « + numTranslucentCrn as string |
|
lblNumOpacity.text = «Opacity: « + numOpacityCrn as string |
|
lblNumDisplace.text = «Displacement: « + numDisplacementCrn as string |
|
lblNumCrnLight.text = «Number of CoronaLightMtl(s): « + CrnLightMat.count as string |
|
lblNumEmitting.text = «Emitting light (Direct): « + numEmittingLightMat as string |
|
) |
|
), |
|
|
|
CoronaMtlConvClassRoll = rollout CoronaMtlConvClassRoll «Convert by class« width:250 height:480 ( |
|
label lblDesc «Convert any material class to a default CoronaPhysicalMtl. You can select multiple classes at once.« pos:[4, 4] width:240 height:60 |
|
multilistbox mlb «« pos:[4, 50] width:240 height:30 items:(collectMaterialClasses()) |
|
button convertClasses «Convert to default CoronaPhysicalMtl« pos:[4, 450] width:240 |
|
|
|
on convertClasses pressed do ( |
|
for cls in mlb.selection do ( |
|
for mtl in (getclassinstances (execute mlb.items[cls])) where (classof mtl != CoronaPhysicalMtl) do ( |
|
try ( |
|
replaceInstances mtl (CoronaPhysicalMtl name:mtl.name) |
|
) catch («Unknown error occurred.«) |
|
) |
|
) |
|
) |
|
), |
|
|
|
fn setMapsViewportVisibility enabled selected:false =( |
|
if selected then ( |
|
for selectedInstance in selection do ( |
|
if selectedInstance.material != undefined do ( |
|
recursiveShowMaps selectedInstance.material enabled |
|
) |
|
) |
|
) else ( |
|
for classInstance in (getclassinstances CoronaPhysicalMtl) do ( |
|
try ( |
|
showTextureMap classInstance enabled |
|
) catch () |
|
) |
|
— Remove in the future, once we completely deprecate CoronaLegacyMtl. |
|
for classInstance in (getclassinstances CoronaLegacyMtl) do ( |
|
try ( |
|
showTextureMap classInstance enabled |
|
) catch () |
|
) |
|
) |
|
), |
|
|
|
— Disables displacement maps of all CoronaPhysicalMtl(s). |
|
fn disableDisplacementMaps =( |
|
with animate off ( |
|
for classInstance in (getclassinstances CoronaPhysicalMtl) do ( |
|
classInstance.displacementTexmapOn = false |
|
) |
|
) |
|
), |
|
|
|
fn disableCoronaRoundEdgesMapsLegacyMode =( |
|
with animate off ( |
|
for classInstance in (getclassinstances CoronaRoundEdges) do ( |
|
classInstance.legacy = false |
|
) |
|
) |
|
), |
|
|
|
fn convertClass =( |
|
createDialog CoronaMtlConvClassRoll |
|
), |
|
|
|
fn CoronaMtlStats =( |
|
createDialog CoronaMtlConvStatsRoll |
|
), |
|
|
|
fn resetCompactMaterialEditor =( |
|
for i = 1 to 24 do ( |
|
meditmaterials[i] = CoronaPhysicalMtl name:((formattedPrint i format:«.2d«) + « — CoronaPhysicalMtl«) |
|
) |
|
), |
|
|
|
fn replaceMapInstances map newMap =( |
|
— Wraps replaceInstances function to fix bug which sometimes duplicates replaced nodes in |
|
— SME (Slate Material Editor). |
|
|
|
— Get node count per SME view, so that the views where no duplicate node is created |
|
— don’t have to be checked. |
|
smeNodeCount = (for i = 1 to sme.GetNumViews() collect ((sme.getView i).GetNumNodes())) |
|
|
|
— Replaces nodes «reference» member that is pointing to map to point to newMap |
|
replaceInstances map newMap |
|
|
|
— Since nodes with the newMap reference can be in multiple SME views, we have to check |
|
— all of them. |
|
for viewIndex = 1 to sme.GetNumViews() do ( |
|
mapSmeView = sme.GetView viewIndex |
|
mapNode = mapSmeView.GetNodeByRef newMap |
|
if mapNode != undefined and smeNodeCount[viewIndex] < mapSmeView.GetNumNodes() do ( |
|
|
|
— The duplicate nodes can obtain some of the connections to the dependent nodes, |
|
— therefore we have to reconnect the dependent nodes to the mapNode before |
|
— deleting the duplicates. Even though we also check nodes without direct |
|
— connection to the mapNode or its duplicates (which is in this case |
|
— unnecessary), it doesn’t have a huge negative performance impact. |
|
dependents = refs.dependents newMap |
|
dependentNodes = for d in dependents where (dependentNode = mapSmeView.GetNodeByRef d) != undefined collect dependentNode |
|
for dependentNode in dependentNodes do ( |
|
— In 3ds Max 2016 and older, the class of dependentNode can sometimes be |
|
— MixinInterface. Calling getPropNames() function on such class results in an |
|
— exception being thrown. |
|
if classof dependentNode != MixinInterface then ( |
|
for propertyName in (getPropNames dependentNode.reference) do ( |
|
property = getProperty dependentNode.reference propertyName |
|
|
|
— Remove and return the connection to the newMap reference: this will |
|
— connect only the mapNode (i.e. node previously containing the replaced |
|
— map) instead of randomly connecting one of the duplicate nodes. |
|
if (isKindOf property arrayParameter) then ( |
|
— if the property is an array, it’s only a shallow copy and the |
|
— values stored in the array are references. |
|
for i = 1 to property.count do ( |
|
if property[i] == newMap do ( |
|
property[i] = undefined |
|
property[i] = newMap |
|
) |
|
) |
|
) else if property == newMap do ( |
|
setProperty dependentNode.reference propertyName undefined |
|
setProperty dependentNode.reference propertyName newMap |
|
) |
|
) |
|
) |
|
) |
|
|
|
— Setting selection to the newMap will also select all the duplicate nodes, |
|
— which then can be easily deleted after unselecting the mapNode. |
|
mapSmeView.SetSelectedNodes newMap |
|
mapNode.selected = false |
|
mapSmeView.DeleteSelection() |
|
) |
|
) |
|
), |
|
|
|
fn convertBitmapToCoronaBitmap =( |
|
with animate off ( |
|
for map in getclassinstances Bitmaptexture do ( |
|
local newMap = owner.mapConvMethods.convertFrom_BitmapTexture map |
|
if newMap != #NoReplacement do ( |
|
replaceMapInstances map newMap |
|
) |
|
) |
|
) |
|
), |
|
|
|
fn convertCoronaBitmapToBitmap =( |
|
with animate off ( |
|
for map in getclassinstances CoronaBitmap do ( |
|
local newMap = owner.mapConvMethods.convertFrom_CoronaBitmap map |
|
if newMap != #NoReplacement do ( |
|
replaceMapInstances map newMap |
|
) |
|
) |
|
) |
|
), |
|
|
|
fn fixCoronaNormalGamma =( |
|
with animate off ( |
|
for mp in (getClassInstances CoronaNormal) do ( |
|
if mp.gammaWarning then ( |
|
mp.addGamma = not mp.addGamma |
|
) |
|
) |
|
) |
|
), |
|
|
|
fn getVersion =( |
|
owner.CoronaConverterVersion |
|
) |
|
) |
|
converterTools owner:this |
|
), |
|
|
|
fn scenematerialsUpdateHack =( |
|
— DIRTY HACK to force max to save something and re-evaluate the scenematerials tree, so no «dead» classes will remain somewhere. |
|
— if not done, e.g. Autodesk_Material warnings will pop up all the time if there was a Adsk mtl because it’s still referenced somehwere. |
|
tempFile = GetDir #temp + «/_tempSceneMaterialsHack.max« |
|
saveNodes #() tempFile |
|
deleteFile tempFile |
|
), |
|
|
|
fn createErrorReports =( |
|
rollout ErrorReportRollout «Error Report« width:400 height:500 ( |
|
local owner = if owner != undefined do ( |
|
owner |
|
) |
|
local report |
|
label lbl1 «Conversion finished but one or more errors occurred!« |
|
label lbl2 «Please save the ErrorReport.txt below and send it to us via our support portal:« |
|
hyperLink lnk «https://coronarenderer.freshdesk.com/support/tickets/new« address:«https://coronarenderer.freshdesk.com/support/tickets/new« color:owner.converterSettings.UI_LINK_COLOR visitedColor:owner.converterSettings.UI_LINK_COLOR offset:[50, 0] |
|
dotNetControl edxErr «System.Windows.Forms.TextBox« pos:[0, 60] width:400 height:400 |
|
button btnCopy «Save ErrorReport.txt« height:30 |
|
|
|
on ErrorReportRollout open do ( |
|
edxErr.Multiline = true |
|
edxErr.ReadOnly = true |
|
edxErr.backcolor = edxErr.backcolor.FromArgb 60 60 60 |
|
edxErr.foreColor = edxErr.foreColor.FromArgb 255 120 0 |
|
|
|
if not converterSettings.silent do ( |
|
report = «« |
|
report += «>>> SCENE Info: <<<rn« |
|
report += «Converter version: « + owner.converterTools.getVersion() + «rn« |
|
report += «Max version: « + (maxversion())[1] as string + «rn« |
|
report += «Installed Vray plugins: « |
|
|
|
for i in RendererClass.classes where substring (i as string) 1 5 == «V_Ray« do ( |
|
report += i as string + « « |
|
) |
|
report += «rn« |
|
|
|
for i in converterTempData.errorBuffer do ( |
|
report += (i + «rnrn«) |
|
) |
|
|
|
ErrorReportRollout.edxErr.text = report |
|
) |
|
) |
|
|
|
on btnCopy pressed do ( |
|
loc = getSavePath «Location to store ErrorReport.txt« |
|
if loc != undefined do ( |
|
file = createFile (pathConfig.appendPath loc «ErrorReport.txt«) |
|
if file != undefined do ( |
|
format report to:file — edxErr.text |
|
) |
|
close file |
|
) |
|
) |
|
) |
|
|
|
ErrorReportRollout.owner = this |
|
|
|
if converterTempData.errorBuffer.count != 0 do ( |
|
createDialog ErrorReportRollout |
|
) |
|
converterTempData.errorBuffer = #() |
|
), |
|
|
|
fn errorCatching functionName orig =( |
|
errcls = classof orig |
|
if converterSettings.useTryCatchBugReporting then ( |
|
try ( |
|
out = functionName orig |
|
) catch ( |
|
append converterTempData.errorBuffer («Error occurred in « + errcls as string + « : « + orig as string + «rn« + getCurrentException()) |
|
out = orig |
|
) |
|
) else ( |
|
out = functionName orig |
|
) |
|
|
|
out |
|
), |
|
|
|
fn getGlossyConversionOutputMap type =( |
|
— Most of the code in this function is taken from the cg-talk thread |
|
— «Is it possible To Create and Edit Output Map Curve?» |
|
— http://forums.cgsociety.org/showthread.php?f=98&t=993502 |
|
— Thanks goes to denisT for sharing these great tech tips. |
|
outputmap = undefined |
|
backupMtl = undefined |
|
selectedSlot = undefined |
|
isEditOpen = undefined |
|
|
|
try ( |
|
destroydialog easyCCurve |
|
) catch () |
|
|
|
rollout easyCCurve «Easy CCurve« width:208 height:215 |
|
( |
|
fn mouseWindowMove hwnd x y sx sy = |
|
( |
|
fn makeParam LoWord HiWord = |
|
( |
|
bit.or (bit.shift HiWord 16) (bit.and LoWord 0xFFFF) |
|
) |
|
WM_LBUTTONDOWN = 0x0201 |
|
WM_LBUTTONUP = 0x0202 |
|
WM_MOUSEMOVE = 0x0200 |
|
MK_LBUTTON = 0x0001 |
|
|
|
p0 = makeParam x y |
|
p1 = makeParam (x + sx) (y + sy) |
|
|
|
uiaccessor.sendmessage hwnd WM_LBUTTONDOWN 0 p0 |
|
uiaccessor.sendmessage hwnd WM_MOUSEMOVE MK_LBUTTON p1 |
|
uiaccessor.sendmessage hwnd WM_LBUTTONUP 0 p1 |
|
) |
|
curveControl cc numcurves:1 width:200 height:200 pos:[4, 4] zoomvalues:[200, 100] scrollvalues:[4, 2] uiFlags:#() rcmFlags:#() |
|
) |
|
createdialog easyCCurve style:#() pos:[—1000, 300] |
|
|
|
with redraw off ( |
|
d_hwnd = (windows.getChildHWND 0 easyCCurve.title)[1] |
|
c_hwnd = for w in (windows.getChildrenHWND d_hwnd) where w[4] == «DefCurveWindow« do ( |
|
exit with w[1] |
|
) |
|
|
|
cc = easyCCurve.cc.curves[1] |
|
cc.color = black |
|
cc.numpoints = 4 |
|
|
|
pp = easyCCurve.cc.curves[1].points |
|
pp.selected = on |
|
|
|
case type of ( |
|
#VrayGgxToClampedGgx: ( — Deprecated |
|
cc.numpoints = 4 |
|
pp = easyCCurve.cc.curves[1].points |
|
pp.selected = on |
|
|
|
pp[1].value = [0, 0.017] |
|
|
|
pp[2].value = [0.38, 0.01] |
|
pp[2].outtangent = [0.01, 0.135] |
|
|
|
pp[3].value = [0.65, 0.375] |
|
pp[3].intangent = [—0.25, —0.175] |
|
pp[3].outtangent = [0.25, 0.175] |
|
|
|
pp[4].value = [1.0, 1.0] |
|
pp[4].intangent = [—0.06, —0.06] |
|
) |
|
default: ( — V-Ray Blinn to Corona GGX (new) |
|
cc.numpoints = 3 |
|
pp = easyCCurve.cc.curves[1].points |
|
pp.selected = on |
|
|
|
pp[1].value = [0, 0.01] |
|
|
|
pp[2].value = [0.19, 0.01] |
|
pp[2].outtangent = [0.45, 0.48] |
|
|
|
pp[3].value = [1.0, 1.0] |
|
pp[3].intangent = [—0.16, —0.25] |
|
) |
|
|
|
) |
|
|
|
— make backups |
|
backupMtl = meditmaterials[1] |
|
selectedSlot = medit.GetActiveMtlSlot() |
|
isEditOpen = MatEditor.isOpen() |
|
matEditorMode = MatEditor.mode |
|
—mateditor.close() |
|
|
|
if matEditorMode == #advanced then ( |
|
MatEditor.mode = #basic |
|
) |
|
|
|
— Make Output Map |
|
outputmap = output name:«GlossyConversionBlinnToGGX« |
|
medit.PutMtlToMtlEditor outputmap 1 |
|
medit.SetActiveMtlSlot 1 on |
|
|
|
— Init Mono_Color_Map |
|
|
|
mateditor.open() |
|
c = windows.getchildhwnd (windows.getchildhwnd 0 («Material Editor — « + outputmap.name))[1] «Enable Color Map« |
|
|
|
BM_SETCHECKED = 0x00F1 |
|
UIAccessor.SendMessage c[1] BM_SETCHECKED 1 0 |
|
UIAccessor.PressButton c[1] |
|
|
|
— Replace Curve |
|
replaceinstances outputmap.output.Mono_Color_Map.curve_1 easyCCurve.cc.curves[1][1].parent |
|
—medit.SetActiveMtlSlot 1 on |
|
|
|
— restore backups |
|
medit.PutMtlToMtlEditor backupMtl 1 |
|
medit.SetActiveMtlSlot selectedSlot on |
|
|
|
if not isEditOpen do ( |
|
MatEditor.Close() |
|
) |
|
MatEditor.mode = matEditorMode |
|
) |
|
destroydialog easyCCurve |
|
free easyCCurve |
|
|
|
outputmap |
|
), |
|
|
|
— structs containing conversion methods for mtl, map, light classes |
|
matConvMethods =( |
|
struct matConvMethods ( |
|
owner, |
|
|
|
fn convertFrom_Standard origMtl =( |
|
r = CoronaLegacyMtl() |
|
r.name = origMtl.name |
|
|
|
origMtl.shaderType = 1 — make sure standard mat shader type is set to default blinn |
|
|
|
—Diffuse |
|
r.levelDiffuse = 1.0 |
|
r.colorDiffuse = origMtl.diffuse |
|
r.texmapDiffuse = origMtl.diffuseMap |
|
if r.texmapDiffuse != undefined then ( |
|
r.texmapOnDiffuse = origMtl.diffuseMapEnable |
|
r.mapamountDiffuse = origMtl.diffuseMapAmount —/ 100.0 |
|
) |
|
|
|
—Reflection |
|
r.levelReflect = (if origMtl.specularLevel > 100.0 then ( |
|
1.0 |
|
) else ( |
|
origMtl.specularLevel / 100.0 |
|
)) |
|
r.colorReflect = origMtl.specular |
|
r.reflectGlossiness = sqrt (origMtl.glossiness / 100.0) |
|
|
|
r.texmapReflect = origMtl.specularLevelMap — Default uses specular level for reflection. |
|
if r.texmapReflect != undefined then ( |
|
r.texmapOnReflect = origMtl.specularLevelMapEnable |
|
r.mapamountReflect = origMtl.specularLevelMapAmount —/ 100.0 |
|
) |
|
|
|
if origMtl.reflectionMap != undefined do ( — But will be overriden if reflection map is supplied. |
|
r.texmapReflect = origMtl.reflectionMap |
|
if r.texmapReflect != undefined then ( |
|
r.texmapOnReflect = origMtl.reflectionMapEnable |
|
r.mapamountReflect = origMtl.reflectionMapAmount —/ 100.0 |
|
) |
|
) |
|
r.texmapReflectGlossiness = origMtl.glossinessMap |
|
if r.texmapReflectGlossiness != undefined then ( |
|
r.texmapOnReflectGlossiness = origMtl.glossinessMapEnable |
|
r.mapamountReflectGlossiness = origMtl.glossinessMapAmount —/ 100.0 |
|
) |
|
|
|
if r.texmapReflectGlossiness == undefined and r.texmapReflect == undefined and r.levelReflect == 0.0 and abs(origMtl.glossiness — 10.0) < 0.01 then ( |
|
r.reflectGlossiness = 1.0 |
|
) |
|
|
|
—Refraction |
|
r.texmapRefract = origMtl.refractionMap |
|
if r.texmapRefract != undefined then ( |
|
r.levelRefract = 1.0 |
|
r.colorRefract = black |
|
r.texmapOnRefract = origMtl.refractionMapEnable |
|
r.mapamountRefract = origMtl.refractionMapAmount —/ 100.0 |
|
) |
|
r.ior = if origMtl.ior < 1.0 then ( |
|
1.0 |
|
) else ( |
|
origMtl.ior |
|
) |
|
|
|
—Bumpmap |
|
r.texmapBump = origMtl.bumpMap |
|
if r.texmapBump != undefined then ( |
|
if (isNormalMap r.texmapBump) then ( |
|
r.texmapOnBump = origMtl.bumpMapEnable |
|
r.mapamountBump = (origMtl.bumpMapAmount / 100.0) |
|
) else ( |
|
r.texmapOnBump = origMtl.bumpMapEnable |
|
r.mapamountBump = (origMtl.bumpMapAmount / 100.0) * VRAY_BUMP_MULTIPLIER |
|
) |
|
) |
|
|
|
—Opacity |
|
r.levelOpacity = origMtl.opacity / 100.0 |
|
r.colorOpacity = white |
|
r.texmapOpacity = origMtl.opacityMap |
|
if r.texmapOpacity != undefined then ( |
|
r.texmapOnOpacity = origMtl.opacityMapEnable |
|
r.mapamountOpacity = origMtl.opacityMapAmount —/ 100.0 |
|
) |
|
|
|
—Emission |
|
r.levelSelfIllum = if origMtl.useSelfIllumColor then ( |
|
1.0 |
|
) else ( |
|
origMtl.selfIllumAmount / 100.0 |
|
) |
|
|
|
r.colorSelfIllum = if origMtl.useSelfIllumColor then ( |
|
origMtl.selfIllumColor |
|
) else ( |
|
r.colorDiffuse |
|
) |
|
|
|
r.texmapSelfIllum = origMtl.selfillumMap |
|
if r.texmapSelfIllum != undefined then ( |
|
r.texmapOnSelfIllum = origMtl.selfillumMapEnable |
|
r.mapamountSelfIllum = origMtl.selfillumMapAmount —/ 100.0 |
|
) else ( |
|
if origMtl.useSelfIllumColor == false and origMtl.selfIllumAmount != 0 then ( |
|
r.colorSelfIllum = r.colorDiffuse |
|
if r.texmapOnDiffuse then ( |
|
r.texmapSelfIllum = r.texmapDiffuse; r.texmapOnSelfIllum = true |
|
) |
|
) |
|
) |
|
|
|
—Displacement |
|
r.texmapDisplace = origMtl.displacementMap |
|
if r.texmapDisplace != undefined then ( |
|
r.texmapOnDisplacement = origMtl.displacementMapEnable |
|
) |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_VRayCarPaintMtl origMtl =( |
|
cpbaseMtl = CoronaLegacyMtl() |
|
cpbaseMtl.name = origMtl.name |
|
if origMtl.coat_strength > 0.0 then ( |
|
cpbaseMtl.name = origMtl.name + «_Base« |
|
cpCoatMtl = CoronaLegacyMtl() |
|
cpCoatMtl.name = origMtl.name + «_Coat« |
|
cpBlendMtl = Blend() |
|
cpBlendMtl.name = origMtl.name |
|
) |
|
|
|
—Base Diffuse |
|
cpbaseMtl.levelDiffuse = 1.0 |
|
cpbaseMtl.colorDiffuse = origMtl.base_color |
|
cpbaseMtl.texmapDiffuse = origMtl.texmap_base_color |
|
if cpbaseMtl.texmapDiffuse != undefined then ( |
|
cpbaseMtl.texmapOnDiffuse = origMtl.texmap_base_color_on |
|
cpbaseMtl.mapamountDiffuse = origMtl.texmap_base_color_multiplier —/ 100.0 |
|
) |
|
—Base Reflection |
|
cpbaseMtl.levelReflect = origMtl.base_reflection |
|
cpbaseMtl.colorReflect = origMtl.base_color |
|
cpbaseMtl.texmapReflect = origMtl.texmap_base_reflection |
|
if cpbaseMtl.texmapReflect != undefined then ( |
|
cpbaseMtl.texmapOnReflect = origMtl.texmap_base_reflection_on |
|
cpbaseMtl.mapamountReflect = origMtl.texmap_base_reflection_multiplier —/ 100.0 |
|
) |
|
cpbaseMtl.fresnelIor = 50.0 |
|
cpbaseMtl.reflectGlossiness = 1.0 — sqrt(1.0 — origMtl.base_glossiness) |
|
cpbaseMtl.texmapReflectGlossiness = origMtl.texmap_base_glossiness |
|
if cpbaseMtl.texmapReflectGlossiness != undefined then ( |
|
if owner.converterTempData.glossyConversionOutputMapVrayBlinnCoronaClGgx == undefined do ( |
|
owner.converterTempData.glossyConversionOutputMapVrayBlinnCoronaClGgx = owner.getGlossyConversionOutputMap #VrayBlinnToClampedGgx |
|
) |
|
outmp = copy owner.converterTempData.glossyConversionOutputMapVrayBlinnCoronaClGgx |
|
outmp.map1 = cpbaseMtl.texmapReflectGlossiness |
|
cpbaseMtl.texmapReflectGlossiness = outmp |
|
|
|
cpbaseMtl.texmapOnReflectGlossiness = origMtl.texmap_base_glossiness_on |
|
cpbaseMtl.mapamountReflectGlossiness = origMtl.texmap_base_glossiness_multiplier —/ 100.0 |
|
) |
|
—Base Bumpmap |
|
cpbaseMtl.texmapBump = origMtl.texmap_base_bump |
|
if cpbaseMtl.texmapBump != undefined then ( |
|
cpbaseMtl.texmapOnBump = origMtl.texmap_base_bump_on |
|
cpbaseMtl.mapamountBump = (origMtl.texmap_base_bump_multiplier / 100.0) * VRAY_BUMP_MULTIPLIER |
|
) |
|
|
|
if cpBlendMtl != undefined then ( |
|
—Coat Diffuse |
|
cpCoatMtl.levelDiffuse = 1.0 |
|
cpCoatMtl.colorDiffuse = black |
|
—Coat Reflection |
|
cpCoatMtl.levelReflect = 1.0 |
|
cpCoatMtl.colorReflect = origMtl.coat_color |
|
cpCoatMtl.texmapReflect = origMtl.texmap_coat_color |
|
if cpCoatMtl.texmapReflect != undefined then ( |
|
cpCoatMtl.texmapOnReflect = origMtl.texmap_coat_color_on |
|
cpCoatMtl.mapamountReflect = origMtl.texmap_coat_color_multiplier —/ 100.0 |
|
) |
|
cpCoatMtl.fresnelIor = 25.0 |
|
cpCoatMtl.reflectGlossiness = 1.0 — sqrt(1.0 — origMtl.coat_glossiness) |
|
cpCoatMtl.texmapReflectGlossiness = origMtl.texmap_coat_glossiness |
|
if cpCoatMtl.texmapReflectGlossiness != undefined then ( |
|
if owner.converterTempData.glossyConversionOutputMapVrayBlinnCoronaClGgx == undefined do ( |
|
owner.converterTempData.glossyConversionOutputMapVrayBlinnCoronaClGgx = owner.getGlossyConversionOutputMap #VrayBlinnToClampedGgx |
|
) |
|
outmp = copy owner.converterTempData.glossyConversionOutputMapVrayBlinnCoronaClGgx |
|
outmp.map1 = cpCoatMtl.texmapReflectGlossiness |
|
cpCoatMtl.texmapReflectGlossiness = outmp |
|
|
|
cpCoatMtl.texmapOnReflectGlossiness = origMtl.texmap_coat_glossiness_on |
|
cpCoatMtl.mapamountReflectGlossiness = origMtl.texmap_coat_glossiness_multiplier —/ 100.0 |
|
) |
|
—Coat Bumpmap |
|
cpCoatMtl.texmapBump = origMtl.texmap_coat_bump |
|
if cpCoatMtl.texmapBump != undefined then ( |
|
cpCoatMtl.texmapOnBump = origMtl.texmap_coat_bump_on |
|
cpCoatMtl.mapamountBump = origMtl.texmap_coat_bump_multiplier / 100.0 |
|
) |
|
|
|
cpBlendMtl.MAP1 = cpbaseMtl |
|
cpBlendMtl.MAP2 = cpCoatMtl |
|
cpBlendMtl.mixAmount = origMtl.coat_strength * 100.0 |
|
|
|
if origMtl.texmap_coat_strength != undefined then ( |
|
cpBlendMtl.maskEnabled = origMtl.texmap_coat_strength_on |
|
cpBlendMtl.Mask = origMtl.texmap_coat_strength |
|
) |
|
|
|
cpBlendMtl |
|
) else ( |
|
cpbaseMtl |
|
) |
|
), |
|
|
|
fn convertFrom_MRCarPaintMaterial origMtl =( |
|
cpbaseMtl = CoronaLegacyMtl() |
|
cpbaseMtl.name = origMtl.name + «_Base« |
|
cpCoatMtl = CoronaLegacyMtl() |
|
cpCoatMtl.name = origMtl.name + «_Coat« |
|
cpBlendMtl = Blend() |
|
cpBlendMtl.name = origMtl.name |
|
|
|
—Base Diffuse |
|
cpbaseMtl.levelDiffuse = 1.0 |
|
cpbaseMtl.colorDiffuse = black |
|
cpbaseMtl.texmapDiffuse = falloff() |
|
cpbaseMtl.texmapOnDiffuse = true |
|
cpbaseMtl.texmapDiffuse.color1 = origMtl.base_color |
|
cpbaseMtl.texmapDiffuse.color2 = origMtl.edge_color |
|
cpbaseMtl.texmapDiffuse.MAP1 = origMtl.base_color_shader |
|
cpbaseMtl.texmapDiffuse.MAP2 = origMtl.edge_color_shader |
|
|
|
—Base Reflection |
|
cpbaseMtl.levelReflect = 1.0 |
|
cpbaseMtl.texmapReflect = cpbaseMtl.texmapDiffuse |
|
cpbaseMtl.fresnelIor = 2.5 |
|
cpbaseMtl.reflectGlossiness = 0.3 |
|
|
|
—Coat Diffuse |
|
cpCoatMtl.levelDiffuse = 1.0 |
|
cpCoatMtl.colorDiffuse = black |
|
—Coat Reflection |
|
cpCoatMtl.levelReflect = 1.0 |
|
cpCoatMtl.colorReflect = origMtl.reflection_color |
|
cpCoatMtl.fresnelIor = 2.5 |
|
|
|
cpBlendMtl.MAP1 = cpbaseMtl |
|
cpBlendMtl.MAP2 = cpCoatMtl |
|
cpBlendMtl.mixAmount = 20.0 |
|
|
|
cpBlendMtl |
|
), |
|
|
|
fn convertFrom_ArchAndDesign origMtl =( |
|
r = CoronaLegacyMtl() |
|
r.name = origMtl.name |
|
|
|
—Diffuse |
|
r.levelDiffuse = origMtl.diff_weight |
|
r.colorDiffuse = (color origMtl.diff_color.r origMtl.diff_color.g origMtl.diff_color.b) — is not converting rgba colors, therefore r,g,b seperation |
|
r.texmapDiffuse = origMtl.diff_color_map |
|
if r.texmapDiffuse != undefined then ( |
|
r.texmapOnDiffuse = origMtl.diff_color_map_on |
|
) |
|
|
|
—Reflection |
|
r.levelReflect = origMtl.refl_weight |
|
r.colorReflect = (color origMtl.refl_color.r origMtl.refl_color.g origMtl.refl_color.b) |
|
r.texmapReflect = origMtl.refl_color_map |
|
if r.texmapReflect != undefined then ( |
|
r.texmapOnReflect = origMtl.refl_color_map_on |
|
) |
|
r.fresnelIor = if origMtl.refr_ior < 1.0 then ( |
|
1.0 |
|
) else ( |
|
origMtl.refr_ior — must use refraction ior since there is no seperate ior setting for reflection, maybe i’ll add some «conversion» later |
|
) |
|
r.texmapFresnelIor = origMtl.refr_ior_map |
|
if r.texmapFresnelIor != undefined then ( |
|
r.texmapOnFresnelIor = (origMtl.refr_ior_map_on and origMtl.refl_func_fresnel) — only active when global ior map on and brdf radiobutton set to «by IOR» |
|
) |
|
r.reflectGlossiness = origMtl.refl_gloss |
|
r.texmapReflectGlossiness = origMtl.refl_gloss_map |
|
if r.texmapReflectGlossiness != undefined then ( |
|
r.texmapOnReflectGlossiness = origMtl.refl_gloss_map_on |
|
) |
|
|
|
—Refraction |
|
r.levelRefract = origMtl.refr_weight |
|
r.colorRefract = (color origMtl.refr_color.r origMtl.refr_color.g origMtl.refr_color.b) |
|
r.texmapRefract = origMtl.refr_color_map |
|
if r.texmapRefract != undefined then ( |
|
r.texmapOnRefract = origMtl.refr_color_map_on |
|
) |
|
r.ior = if origMtl.refr_ior < 1.0 then ( |
|
1.0 |
|
) else ( |
|
if origMtl.refr_ior > 10.0 then ( |
|
10.0 |
|
) else ( |
|
origMtl.refr_ior |
|
) |
|
) |
|
r.texmapIor = origMtl.refr_ior_map |
|
if r.texmapIor != undefined then ( |
|
r.texmapOnIor = origMtl.refr_color_map_on |
|
) |
|
r.refractGlossiness = origMtl.refr_gloss |
|
r.texmapRefractGlossiness = origMtl.refr_gloss_map |
|
if r.texmapRefractGlossiness != undefined then ( |
|
r.texmapOnRefractGlossiness = origMtl.refr_gloss_map_on |
|
) |
|
|
|
— Glassmode |
|
if origMtl.opts_1sided == off then ( |
|
) else ( |
|
r.thin = true |
|
) |
|
|
|
—Translucency |
|
if origMtl.refr_trans_on == false then ( |
|
r.levelTranslucency = 0.0 |
|
) else ( |
|
—r.levelTranslucency = origMtl.refr_transw |
|
r.levelTranslucency = origMtl.refr_weight |
|
r.levelRefract = (1— origMtl.refr_transw) |
|
) |
|
r.colorTranslucency = (color origMtl.refr_transc.r origMtl.refr_transc.g origMtl.refr_transc.b) |
|
r.texmapTranslucency = origMtl.refr_transc_map |
|
if r.texmapTranslucency != undefined then ( |
|
r.texmapOnTranslucency = origMtl.refr_transc_map_on |
|
) |
|
|
|
—Opacity |
|
r.levelOpacity = 1.0 |
|
r.colorOpacity = white |
|
r.texmapOpacity = origMtl.cutout_map |
|
if r.texmapOpacity != undefined then ( |
|
r.texmapOnOpacity = origMtl.cutout_map_on |
|
) |
|
|
|
—Emission |
|
if origMtl.self_illum_on then ( |
|
r.levelSelfIllum = origMtl.self_illum_int_arbitrary |
|
) |
|
r.colorSelfIllum = (color origMtl.self_illum_color_filter.r origMtl.self_illum_color_filter.g origMtl.self_illum_color_filter.b) |
|
r.texmapSelfIllum = origMtl.self_illum_map |
|
if r.texmapSelfIllum != undefined then ( |
|
r.texmapOnSelfIllum = origMtl.self_illum_map_on |
|
) |
|
|
|
—Bumpmap |
|
r.texmapBump = origMtl.bump_map |
|
if r.texmapBump != undefined then ( |
|
r.texmapOnBump = origMtl.bump_map_on |
|
r.mapamountBump = origMtl.bump_map_amt |
|
) |
|
|
|
—RoundedCorners |
|
if origMtl.opts_round_corners_on then ( |
|
local rcmap = CoronaRoundEdges() |
|
rcmap.radius = origMtl.opts_round_corners_radius |
|
rcmap.mapAdditionalBump = r.texmapBump |
|
rcmap.mapOnAdditional = r.texmapOnBump |
|
r.texmapBump = rcmap |
|
) |
|
|
|
—Anisotropy |
|
r.anisotropy = if origMtl.anisotropy >= 1.0 then ( |
|
(origMtl.anisotropy — 1.0) / 9.0 |
|
) else ( |
|
origMtl.anisotropy — 1.0 |
|
) |
|
r.texmapReflectAnisotropy = origMtl.anisotropy_map |
|
if r.texmapReflectAnisotropy != undefined then ( |
|
r.texmapOnAnisotropy = origMtl.anisotropy_map_on |
|
) |
|
r.anisotropyRotation = origMtl.anisoangle |
|
r.texmapReflectAnisotropyRotation = origMtl.anisoangle_map |
|
if r.texmapReflectAnisotropyRotation != undefined then ( |
|
r.texmapOnAnisotropyRotation = origMtl.anisoangle_map_on |
|
) |
|
—Displacement |
|
r.texmapDisplace = origMtl.displacement_map |
|
if r.texmapDisplace != undefined then ( |
|
r.texmapOnDisplacement = origMtl.displacement_map_on |
|
) |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_fR_Advanced origMtl =( |
|
r = CoronaLegacyMtl() |
|
r.name = origMtl.name |
|
|
|
—Diffuse |
|
r.levelDiffuse = if origMtl.diffuseMultiplier > 100.0 then ( |
|
1.0 |
|
) else ( |
|
origMtl.diffuseMultiplier / 100.0 |
|
) |
|
r.colorDiffuse = origMtl.diffuseColor |
|
r.texmapDiffuse = origMtl.diffuseMap |
|
if r.texmapDiffuse != undefined then ( |
|
r.texmapOnDiffuse = origMtl.useDiffuseMap |
|
r.mapamountDiffuse = origMtl.diffuseMapAmount —/100.0 |
|
) |
|
|
|
—Reflection |
|
r.levelReflect = 1.0 |
|
r.colorReflect = origMtl.reflectFilter |
|
r.texmapReflect = origMtl.reflectMap |
|
if r.texmapReflect != undefined then ( |
|
r.texmapOnReflect = origMtl.useReflectMap |
|
r.mapamountReflect = origMtl.reflectMapAmount —/ 100.0 |
|
) |
|
r.fresnelIor = if origMtl.reflectIOR < 1.0 then ( |
|
1.0 |
|
) else ( |
|
origMtl.reflectIOR |
|
) |
|
r.texmapFresnelIor = origMtl.reflectIORMap |
|
if r.texmapFresnelIor != undefined then ( |
|
r.texmapOnFresnelIor = origMtl.useReflectIORMap |
|
r.mapamountFresnelIor = origMtl.reflectIORMapAmount —/ 100.0 |
|
) |
|
r.reflectGlossiness = (1.0 — (origMtl.reflectGlossy / 100.0)) |
|
r.texmapReflectGlossiness = origMtl.reflectBlurryMap — !! Might want to add a invert map here to match others engines 1-0 range !! |
|
if r.texmapReflectGlossiness != undefined then ( |
|
r.texmapOnReflectGlossiness = origMtl.useReflectBlurryMap |
|
r.mapamountReflectGlossiness = origMtl.reflectBlurryMapAmount —/ 100.0 |
|
) |
|
|
|
—Refraction |
|
r.levelRefract = 1.0 |
|
r.colorRefract = origMtl.refractFilter |
|
r.texmapRefract = origMtl.refractMap |
|
if r.texmapRefract != undefined then ( |
|
r.texmapOnRefract = origMtl.useRefractMap |
|
r.mapamountRefract = origMtl.refractMapAmount —/ 100.0 |
|
) |
|
r.ior = if origMtl.refractIOR < 1.0 then ( |
|
1.0 |
|
) else ( |
|
if origMtl.refractIOR > 10.0 then ( |
|
10.0 |
|
) else ( |
|
origMtl.refractIOR |
|
) |
|
) |
|
r.texmapIor = origMtl.refractIORMap |
|
if r.texmapIor != undefined then ( |
|
r.texmapOnIor = origMtl.useRefractIORMap |
|
r.mapamountIor = origMtl.refractIORMapAmount —/ 100.0 |
|
) |
|
r.refractGlossiness = (1.0 — (origMtl.refractGlossy / 100.0)) |
|
r.texmapRefractGlossiness = origMtl.refractBlurryMap |
|
if r.texmapRefractGlossiness != undefined then ( |
|
r.texmapOnRefractGlossiness = origMtl.useRefractBlurryMap |
|
r.mapamountRefractGlossiness = origMtl.refractBlurryMapAmount —/ 100.0 |
|
) |
|
|
|
—Opacity |
|
r.levelOpacity = 1.0 |
|
r.colorOpacity = white |
|
r.texmapOpacity = origMtl.opacityMap |
|
if r.texmapOpacity != undefined then ( |
|
r.texmapOnOpacity = origMtl.useOpacityMap |
|
r.mapamountOpacity = origMtl.opacityMapAmount —/ 100.0 |
|
) |
|
|
|
—Emission |
|
r.levelSelfIllum = origMtl.selfIllumMultiplier / 100.0 |
|
r.colorSelfIllum = origMtl.selfIllum |
|
r.texmapSelfIllum = origMtl.selfillumMap |
|
if r.texmapSelfIllum != undefined then ( |
|
r.texmapOnSelfIllum = origMtl.useSelfIllumMap |
|
r.mapamountSelfIllum = origMtl.selfillumMapAmount —/100.0 |
|
) |
|
|
|
—Bumpmap |
|
r.texmapBump = origMtl.bumpMap |
|
if r.texmapBump != undefined then ( |
|
r.texmapOnBump = origMtl.useBumpMap |
|
r.mapamountBump = origMtl.bumpMapAmount / 100.0 |
|
) |
|
|
|
—Absorption |
|
if origMtl.useRefrAbsorption == true then ( |
|
r.absorptionDistance = origMtl.refrAbsorption |
|
r.absorptionColor = origMtl.refrAbsorpColor |
|
) |
|
|
|
—Anisotropy |
|
r.anisotropy = origMtl.Anisotropic / 100.0 |
|
r.texmapReflectAnisotropy = origMtl.anisoAmountReflectionMap |
|
if r.texmapReflectAnisotropy != undefined then ( |
|
r.texmapOnAnisotropy = origMtl.useAnisoAmountReflectionMap |
|
r.mapamountAnisotropy = origMtl.anisoAmountReflectionMapAmount —/100.0 |
|
) |
|
r.anisotropyRotation = origMtl.orientation |
|
r.texmapReflectAnisotropyRotation = origMtl.anisoOrientationReflectionMap |
|
if r.texmapReflectAnisotropyRotation != undefined then ( |
|
r.texmapOnAnisotropyRotation = origMtl.useAnisoOrientationReflectionMap |
|
r.mapamountAnisotropyRotation = origMtl.anisoOrientationReflectionMapAmount —/100.0 |
|
) |
|
—Displacement |
|
r.texmapDisplace = origMtl.MTDMap |
|
if r.texmapDisplace != undefined then ( |
|
r.texmapOnDisplacement = origMtl.useMTDMap |
|
) |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_fR_Architectural origMtl =( |
|
r = CoronaLegacyMtl() |
|
r.name = origMtl.name |
|
|
|
—Diffuse |
|
r.levelDiffuse = if origMtl.diffuse_weight > 1.0 then ( |
|
1.0 |
|
) else ( |
|
origMtl.diffuse_weight |
|
) |
|
r.colorDiffuse = origMtl.diffuse_color |
|
r.texmapDiffuse = origMtl.diffcolor_map |
|
if r.texmapDiffuse != undefined then ( |
|
r.texmapOnDiffuse = origMtl.use_diffcolor_map |
|
) |
|
|
|
—Reflection |
|
r.levelReflect = origMtl.reflectivity |
|
r.colorReflect = (color origMtl.refl_color.r origMtl.refl_color.g origMtl.refl_color.b) |
|
r.texmapReflect = origMtl.reflcolor_map |
|
if r.texmapReflect != undefined then ( |
|
r.texmapOnReflect = origMtl.use_reflcolor_map |
|
) |
|
r.fresnelIor = if origMtl.refr_ior < 1.0 then ( |
|
1.0 |
|
) else ( |
|
origMtl.refr_ior — must use refraction ior since there is no seperate ior setting for reflection, maybe i’ll add some «conversion» later |
|
) |
|
r.texmapFresnelIor = origMtl.ior_map |
|
if r.texmapFresnelIor != undefined then ( |
|
r.texmapOnFresnelIor = (origMtl.use_ior_map and origMtl.brdf_fresnel) — only active when global ior map on and brdf radiobutton set to «by IOR» |
|
) |
|
r.reflectGlossiness = origMtl.refl_gloss |
|
r.texmapReflectGlossiness = origMtl.reflgloss_map |
|
if r.texmapReflectGlossiness != undefined then ( |
|
r.texmapOnReflectGlossiness = origMtl.use_reflgloss_map |
|
) |
|
|
|
—Refraction |
|
r.levelRefract = origMtl.transparency |
|
r.colorRefract = (color origMtl.refr_color.r origMtl.refr_color.g origMtl.refr_color.b) |
|
r.texmapRefract = origMtl.refrcolor_map |
|
if r.texmapRefract != undefined then ( |
|
r.texmapOnRefract = origMtl.use_refrcolor_map |
|
) |
|
r.ior = if origMtl.refr_ior < 1.0 then ( |
|
1.0 |
|
) else ( |
|
if origMtl.refr_ior > 10.0 then ( |
|
10.0 |
|
) else ( |
|
origMtl.refr_ior |
|
) |
|
) |
|
r.texmapIor = origMtl.ior_map |
|
if r.texmapIor != undefined then ( |
|
r.texmapOnIor = origMtl.use_ior_map |
|
) |
|
r.refractGlossiness = origMtl.refr_gloss |
|
r.texmapRefractGlossiness = origMtl.refrgloss_map |
|
if r.texmapRefractGlossiness != undefined then ( |
|
r.texmapOnRefractGlossiness = origMtl.use_refrgloss_map |
|
) |
|
|
|
— Glassmode |
|
r.thin = if origMtl.thin_walled == 0 then ( |
|
false |
|
) else ( |
|
true |
|
) |
|
|
|
—Translucency |
|
if origMtl.refr_translucency == false then ( |
|
r.levelTranslucency = 0.0 |
|
) else ( |
|
—r.levelTranslucency = origMtl.refr_transw |
|
r.levelTranslucency = origMtl.transparency |
|
r.levelRefract = (1— origMtl.refr_trans_weight) |
|
) |
|
r.colorTranslucency = (color origMtl.refr_trans_color.r origMtl.refr_trans_color.g origMtl.refr_trans_color.b) |
|
r.texmapTranslucency = origMtl.transcolor_map |
|
if r.texmapTranslucency != undefined then ( |
|
r.texmapOnTranslucency = origMtl.use_transcolor_map |
|
) |
|
|
|
—Opacity |
|
r.levelOpacity = 1.0 |
|
r.colorOpacity = white |
|
r.texmapOpacity = origMtl.cutout_map |
|
if r.texmapOpacity != undefined then ( |
|
r.texmapOnOpacity = origMtl.use_cutout_map |
|
) |
|
|
|
—Emission |
|
if origMtl.self_illumination_on then ( |
|
r.levelSelfIllum = origMtl.self_illum_intensity |
|
) |
|
r.colorSelfIllum = (color origMtl.self_illum_filter.r origMtl.self_illum_filter.g origMtl.self_illum_filter.b) |
|
r.texmapSelfIllum = origMtl.selfillum_map |
|
if r.texmapSelfIllum != undefined then ( |
|
r.texmapOnSelfIllum = origMtl.use_selfillum_map |
|
) |
|
|
|
—Bumpmap |
|
r.texmapBump = origMtl.bump_map |
|
if r.texmapBump != undefined then ( |
|
r.texmapOnBump = origMtl.use_bump_map |
|
r.mapamountBump = origMtl.bump_map_amount |
|
) |
|
|
|
—RoundedCorners |
|
if origMtl.roundcorners_on then ( |
|
local rcmap = CoronaRoundEdges() |
|
rcmap.radius = origMtl.roundcorners_radius |
|
rcmap.mapAdditionalBump = r.texmapBump |
|
rcmap.mapOnAdditional = r.texmapOnBump |
|
r.texmapBump = rcmap |
|
) |
|
|
|
—Anisotropy |
|
r.anisotropy = if origMtl.anisotropy > 1.0 then ( |
|
(origMtl.anisotropy — 1.0) / 9.0 |
|
) else ( |
|
origMtl.anisotropy — 1.0 |
|
) |
|
r.texmapReflectAnisotropy = origMtl.anisotropy_map |
|
if r.texmapReflectAnisotropy != undefined then ( |
|
r.texmapOnAnisotropy = origMtl.use_anisotropy_map |
|
) |
|
r.anisotropyRotation = origMtl.anisotropy_rotation |
|
r.texmapReflectAnisotropyRotation = origMtl.anisorot_map |
|
if r.texmapReflectAnisotropyRotation != undefined then ( |
|
r.texmapOnAnisotropyRotation = origMtl.use_anisorot_map |
|
) |
|
|
|
—Displacement |
|
r.texmapDisplace = origMtl.displacement_map |
|
if r.texmapDisplace != undefined then ( |
|
r.texmapOnDisplacement = origMtl.use_displacement_map |
|
) |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_AutodeskMtl origMtl =( |
|
owner.converterTempData.AD_mats_found = true |
|
for elem in (refs.dependentNodes origMtl) do ( |
|
appendIfUnique owner.converterTempData.foundAdskMtls elem |
|
) |
|
|
|
matName = origMtl.name |
|
if origMtl.definitionID != «Generic« then ( |
|
origMtl = origMtl.ConvertToGeneric |
|
) |
|
r = CoronaLegacyMtl() |
|
r.name = matName |
|
|
|
—Diffuse |
|
r.colorDiffuse = origMtl.Generic_Color as color |
|
r.texmapDiffuse = origMtl.Generic_Image |
|
|
|
if r.texmapDiffuse != undefined then ( |
|
r.texmapOnDiffuse = true |
|
r.mapamountDiffuse = origMtl.Generic_Image_Fade —/ 100.0 |
|
) |
|
|
|
—Reflection |
|
if origMtl.Reflectivity_Enable then ( |
|
r.levelReflect = (origMtl.Reflectivity_Direct / 100.0) |
|
if origMtl.Reflectivity_Direct_Option == 1 then ( |
|
r.texmapReflect = origMtl.Reflectivity_Direct_Map |
|
) |
|
if r.texmapReflect != undefined then ( |
|
r.texmapOnReflect = true |
|
) |
|
r.fresnelIor = 20.0 |
|
) |
|
r.reflectGlossiness = origMtl.Generic_Glossiness — / 100.0 |
|
|
|
—Refraction |
|
if origMtl.Transparency_Enable then ( |
|
r.levelRefract = origMtl.Transparency_Amount / 100.0 |
|
r.colorRefract = white |
|
r.texmapRefract = origMtl.Transparency_Image |
|
if r.texmapRefract != undefined then ( |
|
r.texmapOnRefract = true |
|
r.mapamountRefract = origMtl.Transparency_Image_Fade —/ 100.0 |
|
) |
|
r.ior = origMtl.Transparency_Refraction |
|
) |
|
|
|
—Opacity |
|
if origMtl.Cutouts_Enable then ( |
|
r.levelOpacity = 1.0 |
|
r.colorOpacity = white |
|
r.texmapOpacity = origMtl.Cutouts_Image |
|
if r.texmapOpacity != undefined then ( |
|
r.texmapOnOpacity = origMtl.Cutouts_Enable |
|
) |
|
) |
|
|
|
—Emission |
|
if origMtl.Self_Illumination_Enable then ( |
|
r.levelSelfIllum = (origMtl.Self_Illumination_Luminance / 100.0) |
|
r.colorSelfIllum = origMtl.Self_Illumination_Filter_Color |
|
if origMtl.Self_Illumination_Filter_Color_Option == 1 then ( |
|
r.texmapSelfIllum = origMtl.Self_Illumination_Filter_Color_Map |
|
) |
|
if r.texmapSelfIllum != undefined then ( |
|
r.texmapOnSelfIllum = true |
|
) |
|
) |
|
|
|
—Bumpmap |
|
if origMtl.Bump_Enable then ( |
|
r.texmapBump = origMtl.Bump_Image |
|
if r.texmapBump != undefined then ( |
|
r.texmapOnBump = true |
|
r.mapamountBump = (if origMtl.bump_amount / 100.0 > 0.3 then ( |
|
0.3 |
|
) else ( |
|
origMtl.bump_amount / 100.0 |
|
)) |
|
) |
|
) |
|
|
|
r |
|
), |
|
|
|
— The inputMaterial is expected to be VRayBlendMtl (checked by an assert). |
|
fn convertVRayBlendMtlToCoronaLayeredMtl inputMaterial =( |
|
assert ((classof inputMaterial) == VRayBlendMtl) |
|
|
|
local outputMaterial = CoronaLayeredMtl() |
|
outputMaterial.name = inputMaterial.name |
|
|
|
outputMaterial.baseMtl = inputMaterial.baseMtl |
|
|
|
for index = 1 to inputMaterial.coatMtl.count do ( |
|
outputMaterial.layers[index] = inputMaterial.coatMtl[index] |
|
outputMaterial.amounts[index] = (colorToAverageLuminance inputMaterial.blend[index]) / MAX_COLOR_VALUE * 100.0 |
|
outputMaterial.mixmaps[index] = inputMaterial.texmap_blend[index] |
|
outputMaterial.maskAmounts[index] = inputMaterial.texmap_blend_multiplier[index] |
|
|
|
if outputMaterial.mixmaps[index] != undefined and inputMaterial.texmap_blend_multiplier[index] == 100.0 then ( |
|
outputMaterial.amounts[index] = 100.0 |
|
) |
|
) |
|
|
|
— Parameter available since V-Ray 3.3. |
|
if hasProperty inputMaterial #coatMtl_enable then ( |
|
for index = 1 to inputMaterial.coatMtl_enable.count do ( |
|
outputMaterial.layersOn[index] = inputMaterial.coatMtl_enable[index] |
|
) |
|
) |
|
|
|
/*return*/ outputMaterial |
|
), |
|
|
|
— The inputMaterial is expected to be VRayLightMtl (checked by an assert). |
|
fn convertVRayLightMtlToCoronaLightMtl inputMaterial =( |
|
assert ((classof inputMaterial) == VRayLightMtl) |
|
|
|
local outputMaterial = CoronaLightMtl() |
|
outputMaterial.name = inputMaterial.name |
|
|
|
outputMaterial.color = inputMaterial.color |
|
outputMaterial.intensity = inputMaterial.multiplier |
|
outputMaterial.emitLight = inputMaterial.directLight_on |
|
outputMaterial.twosidedEmission = inputMaterial.twoSided |
|
|
|
outputMaterial.texmap = inputMaterial.texmap |
|
outputMaterial.texmapOn = inputMaterial.texmap_on |
|
|
|
outputMaterial.opacityTexmap = inputMaterial.opacity_texmap |
|
outputMaterial.opacityTexmapOn = inputMaterial.opacity_texmap_on |
|
|
|
/*return*/ outputMaterial |
|
), |
|
|
|
— The inputMaterial is expected to be VRayFastSSS (checked by an assert). |
|
fn convertVRayFastSSSToCoronaPhysicalMtl inputMaterial =( |
|
assert ((classof inputMaterial) == VRayFastSSS) |
|
|
|
local outputMaterial = createDefaultCoronaPhysicalMtl inputMaterial.name |
|
outputMaterial.basecolor = inputMaterial.shallow_color |
|
|
|
/*return*/ outputMaterial |
|
), |
|
|
|
fn convertFrom_VRayFastSSS2 origMtl =( |
|
r = CoronaSkinMtl() |
|
r.name = origMtl.name |
|
|
|
r.skinLevel = 1.0 |
|
r.sssRadiusScale = origMtl.scale |
|
|
|
— sss amount |
|
r.sssAmount = 1.0 — origMtl.diffuse_amount |
|
if origMtl.texmap_diffuse_amount != undefined do ( |
|
r.texmapSssAmount = mix color1:white color2:black mask:origMtl.texmap_diffuse_amount |
|
r.texmapOnSssAmount = origMtl.texmap_diffuse_amount_on |
|
r.mapamountSssAmount = origMtl.texmap_diffuse_amount_multiplier |
|
) |
|
|
|
—overall color |
|
r.sss2Weight = 0.0 |
|
r.sss3Weight = 0.0 |
|
r.skinColor = origMtl.sub_surface_color |
|
r.sss1Color = origMtl.scatter_color |
|
|
|
r.texmapSkinColor = origMtl.texmap_sss_color |
|
if r.texmapSkinColor != undefined then ( |
|
r.texmapOnSkinColor = origMtl.texmap_sss_color_on |
|
r.mapamountSkinColor = origMtl.texmap_sss_color_multiplier |
|
) |
|
r.texmapSss1Color = origMtl.texmap_scatter_color |
|
if r.texmapSss1Color != undefined then ( |
|
r.texmapOnSss1Color = origMtl.texmap_scatter_color_on |
|
r.mapamountSss1Color = origMtl.texmap_scatter_color_multiplier |
|
) |
|
|
|
if origMtl.diffuse_amount > 0.0 or origMtl.texmap_diffuse_amount != undefined then ( |
|
local cm = mix() |
|
cm.color1 = r.skinColor |
|
cm.map1 = r.texmapSkinColor |
|
cm.color2 = origMtl.diffuse_color |
|
cm.map2 = r.texmapSss1Color |
|
cm.mixAmount = origMtl.diffuse_amount |
|
cm.mask = origMtl.texmap_diffuse_amount |
|
|
|
r.texmapSkinColor = cm |
|
) |
|
|
|
—radius |
|
r.sss1Radius = origMtl.scatter_radius |
|
r.texmapSss1Radius = origMtl.texmap_scatter_radius |
|
if r.texmapSss1Radius != undefined then ( |
|
r.texmapOnSss1Radius = origMtl.texmap_scatter_radius_on |
|
r.mapamountSss1Radius = origMtl.texmap_scatter_radius_multiplier |
|
) |
|
|
|
—opacity |
|
if (hasProperty origMtl «texmap_opacity«) then ( |
|
r.opacityLevel = 1.0 |
|
r.opacityColor = white |
|
r.texmapOpacityColor = origMtl.texmap_opacity |
|
if r.texmapOpacityColor != undefined then ( |
|
r.texmapOnOpacityColor = origMtl.texmap_opacity_on |
|
r.mapamountOpacityColor = origMtl.texmap_opacity_multiplier —/ 100.0 |
|
) |
|
) |
|
|
|
—bumpmap |
|
r.texmapBump = origMtl.texmap_bump |
|
if r.texmapBump != undefined then ( |
|
r.texmapOnBump = origMtl.texmap_bump_on |
|
r.mapamountBump = (origMtl.texmap_bump_multiplier / 100.0) * VRAY_BUMP_MULTIPLIER |
|
) |
|
|
|
—displacement |
|
if (hasProperty origMtl «texmap_displacement_on«) then ( |
|
r.texmapDisplace = origMtl.texmap_displacement |
|
if r.texmapDisplace != undefined then ( |
|
r.texmapOnDisplace = origMtl.texmap_displacement_on |
|
) |
|
) |
|
|
|
/*return*/ r |
|
), |
|
|
|
— The inputMaterial is expected to be VRayHairMtl (checked by an assert). |
|
fn convertVRayHairMtlToCoronaHairMtl inputMaterial =( |
|
assert ((classof inputMaterial) == VRayHairMtl) |
|
|
|
local outputMaterial = CoronaHairMtl() |
|
outputMaterial.name = inputMaterial.name |
|
|
|
outputMaterial.melanin = 0.0 |
|
|
|
outputMaterial.colorTint = inputMaterial.secondary_specular |
|
outputMaterial.texmapTint = inputMaterial.texmap_secondary_specular |
|
outputMaterial.texmapOnTint = inputMaterial.texmap_secondary_specular_on |
|
outputMaterial.mapamountTint = inputMaterial.texmap_secondary_specular_multiplier |
|
|
|
outputMaterial.transmission = inputMaterial.transmission |
|
outputMaterial.texmapTransmission = inputMaterial.texmap_transmission |
|
outputMaterial.texmapOnTransmission = inputMaterial.texmap_transmission_on |
|
outputMaterial.mapamountTransmission = inputMaterial.texmap_transmission_multiplier |
|
|
|
outputMaterial.colorDiffuse = inputMaterial.Diffuse |
|
outputMaterial.levelDiffuse = inputMaterial.diffuse_amount |
|
outputMaterial.texmapDiffuse = inputMaterial.texmap_diffuse |
|
outputMaterial.texmapOnDiffuse = inputMaterial.texmap_diffuse_on |
|
outputMaterial.mapAmountDiffuse = inputMaterial.texmap_diffuse_multiplier |
|
|
|
outputMaterial.colorOpacity = inputMaterial.opacity |
|
outputMaterial.texmapOpacity = inputMaterial.texmap_opacity |
|
outputMaterial.texmapOnOpacity = inputMaterial.texmap_opacity_on |
|
outputMaterial.mapamountOpacity = inputMaterial.texmap_opacity_multiplier |
|
|
|
/*return*/ outputMaterial |
|
), |
|
|
|
fn convertFrom_VRaySkinMtl origMtl =( |
|
r = CoronaSkinMtl() |
|
r.name = origMtl.name |
|
|
|
r.skinLevel = 1.0 |
|
r.sssRadiusScale = origMtl.scale |
|
r.sssAmount = if origMtl.max_sss_amount > 1.0 then ( |
|
1.0 |
|
) else ( |
|
origMtl.max_sss_amount |
|
) |
|
r.texmapSssAmount = origMtl.texmap_sss_amount |
|
if r.texmapSssAmount != undefined then ( |
|
r.texmapOnSssAmount = origMtl.texmap_sss_amount_on |
|
r.mapamountSssAmount = origMtl.texmap_sss_amount_multiplier |
|
) |
|
|
|
—Overall color |
|
if origMtl.diffuse_amount > 0.0 then ( |
|
r.skinColor = origMtl.diffuse_color |
|
r.texmapSkinColor = origMtl.texmap_diffuse_color |
|
if r.texmapSkinColor != undefined then ( |
|
r.texmapOnSkinColor = origMtl.texmap_diffuse_color_on |
|
r.mapamountSkinColor = origMtl.texmap_diffuse_color_multiplier |
|
) |
|
) else ( |
|
r.skinColor = origMtl.shallow_color |
|
r.texmapSkinColor = origMtl.texmap_shallow_color |
|
if r.texmapSkinColor != undefined then ( |
|
r.texmapOnSkinColor = origMtl.texmap_shallow_color_on |
|
r.mapamountSkinColor = origMtl.texmap_shallow_color_multiplier |
|
) |
|
) |
|
|
|
—sss layer 1 |
|
r.sss1Color = origMtl.shallow_color |
|
r.texmapSss1Color = origMtl.texmap_shallow_color |
|
if r.texmapSss1Color != undefined then ( |
|
r.texmapOnSss1Color = origMtl.texmap_shallow_color_on |
|
r.mapamountSss1Color = origMtl.texmap_shallow_color_multiplier |
|
) |
|
r.sss1Radius = origMtl.shallow_radius |
|
r.texmapSss1Radius = origMtl.texmap_shallow_radius |
|
if r.texmapSss1Radius != undefined then ( |
|
r.texmapOnSss1Radius = origMtl.texmap_shallow_radius_on |
|
r.mapamountSss1Radius = origMtl.texmap_shallow_radius_multiplier |
|
) |
|
r.sss1Weight = if origMtl.shallow_amount > 1.0 then ( |
|
1.0 |
|
) else ( |
|
origMtl.shallow_amount |
|
) |
|
r.texmapSss1Weight = origMtl.texmap_shallow_amount |
|
if r.texmapSss1Weight != undefined then ( |
|
r.texmapOnSss1Weight = origMtl.texmap_shallow_amount_on |
|
r.mapamountSss1Weight = origMtl.texmap_shallow_amount_multiplier |
|
) |
|
|
|
—sss layer 2 |
|
r.sss2Color = origMtl.medium_color |
|
r.texmapSss2Color = origMtl.texmap_medium_color |
|
if r.texmapSss2Color != undefined then ( |
|
r.texmapOnSss2Color = origMtl.texmap_medium_color_on |
|
r.mapamountSss2Color = origMtl.texmap_medium_color_multiplier |
|
) |
|
r.sss2Radius = origMtl.medium_radius |
|
r.texmapSss2Radius = origMtl.texmap_medium_radius |
|
if r.texmapSss2Radius != undefined then ( |
|
r.texmapOnSss2Radius = origMtl.texmap_medium_radius_on |
|
r.mapamountSss2Radius = origMtl.texmap_medium_radius_multiplier |
|
) |
|
r.sss2Weight = if origMtl.medium_amount > 1.0 then ( |
|
1.0 |
|
) else ( |
|
origMtl.medium_amount |
|
) |
|
r.texmapSss2Weight = origMtl.texmap_medium_amount |
|
if r.texmapSss2Weight != undefined then ( |
|
r.texmapOnSss2Weight = origMtl.texmap_medium_amount_on |
|
r.mapamountSss2Weight = origMtl.texmap_medium_amount_multiplier |
|
) |
|
|
|
—sss layer 3 |
|
r.sss3Color = origMtl.deep_color |
|
r.texmapSss3Color = origMtl.texmap_deep_color |
|
if r.texmapSss3Color != undefined then ( |
|
r.texmapOnSss3Color = origMtl.texmap_deep_color_on |
|
r.mapamountSss3Color = origMtl.texmap_deep_color_multiplier |
|
) |
|
r.sss3Radius = origMtl.deep_radius |
|
r.texmapSss3Radius = origMtl.texmap_deep_radius |
|
if r.texmapSss3Radius != undefined then ( |
|
r.texmapOnSss3Radius = origMtl.texmap_deep_radius_on |
|
r.mapamountSss3Radius = origMtl.texmap_deep_radius_multiplier |
|
) |
|
r.sss3Weight = if origMtl.deep_amount > 1.0 then ( |
|
1.0 |
|
) else ( |
|
origMtl.deep_amount |
|
) |
|
r.texmapSss3Weight = origMtl.texmap_deep_amount |
|
if r.texmapSss3Weight != undefined then ( |
|
r.texmapOnSss3Weight = origMtl.texmap_deep_amount_on |
|
r.mapamountSss3Weight = origMtl.texmap_deep_amount_multiplier |
|
) |
|
|
|
—refl layer 1 |
|
r.reflection1Level = origMtl.primary_reflection_amount |
|
r.reflection1Color = origMtl.primary_reflection_color |
|
r.texmapReflection1Color = origMtl.texmap_primary_reflection_color |
|
if r.texmapReflection1Color != undefined then ( |
|
r.texmapOnReflection1Color = origMtl.texmap_primary_reflection_color_on |
|
r.mapamountReflection1Color = origMtl.texmap_primary_reflection_color_multiplier |
|
) |
|
if origMtl.texmap_primary_reflection_amount != undefined do ( |
|
if r.texmapReflection1Color != undefined then ( |
|
local cm = CoronaMix mixOperation:2 mixInSRgb:false |
|
cm.texmapBottom = r.texmapReflection1Color |
|
cm.texmapTop = origMtl.texmap_primary_reflection_amount |
|
r.texmapReflection1Color = cm |
|
) else ( |
|
r.texmapReflection1Color = origMtl.texmap_primary_reflection_amount |
|
) |
|
) |
|
r.reflection1Glossiness = origMtl.primary_reflection_glossiness |
|
r.texmapReflection1Glossiness = origMtl.texmap_primary_reflection_glossiness |
|
if r.texmapReflection1Glossiness != undefined then ( |
|
r.texmapOnReflection1Color = origMtl.texmap_primary_reflection_glossiness_on |
|
r.mapamountReflection1Color = origMtl.texmap_primary_reflection_glossiness_multiplier |
|
) |
|
r.reflection1Ior = origMtl.primary_reflection_fresnel_ior |
|
|
|
—refl layer 2 |
|
r.reflection2Level = origMtl.secondary_reflection_amount |
|
r.reflection2Color = origMtl.secondary_reflection_color |
|
r.texmapReflection2Color = origMtl.texmap_secondary_reflection_color |
|
if r.texmapReflection2Color != undefined then ( |
|
r.texmapOnReflection2Color = origMtl.texmap_secondary_reflection_color_on |
|
r.mapamountReflection2Color = origMtl.texmap_secondary_reflection_color_multiplier |
|
) |
|
if origMtl.texmap_secondary_reflection_amount != undefined do ( |
|
if r.texmapReflection2Color != undefined then ( |
|
local cm = CoronaMix mixOperation:2 mixInSRgb:false |
|
cm.texmapBottom = r.texmapReflection2Color |
|
cm.texmapTop = origMtl.texmap_secondary_reflection_amount |
|
r.texmapReflection2Color = cm |
|
) else ( |
|
r.texmapReflection2Color = origMtl.texmap_secondary_reflection_amount |
|
) |
|
) |
|
r.reflection2Glossiness = origMtl.secondary_reflection_glossiness |
|
r.texmapReflection2Glossiness = origMtl.texmap_secondary_reflection_glossiness |
|
if r.texmapReflection2Glossiness != undefined then ( |
|
r.texmapOnReflection2Color = origMtl.texmap_secondary_reflection_glossiness_on |
|
r.mapamountReflection2Color = origMtl.texmap_secondary_reflection_glossiness_multiplier |
|
) |
|
r.reflection2Ior = origMtl.secondary_reflection_fresnel_ior |
|
|
|
—opacity |
|
r.opacityLevel = 1.0 |
|
r.opacityColor = origMtl.opacity |
|
r.texmapOpacityColor = origMtl.texmap_opacity |
|
if r.texmapOpacityColor != undefined then ( |
|
r.texmapOnOpacityColor = origMtl.texmap_opacity_on |
|
r.mapamountOpacityColor = origMtl.texmap_opacity_multiplier |
|
) |
|
|
|
—bump |
|
r.texmapBump = origMtl.texmap_bump |
|
if r.texmapBump != undefined then ( |
|
r.texmapOnBump = origMtl.texmap_bump_on |
|
r.mapamountBump = (origMtl.texmap_bump_multiplier / 100.0) * (if (isNormalMap r.texmapBump) then ( |
|
1.0 |
|
) else ( |
|
VRAY_BUMP_MULTIPLIER |
|
)) |
|
) |
|
|
|
—displacement |
|
r.texmapDisplace = origMtl.texmap_displacement |
|
if r.texmapDisplace != undefined then ( |
|
r.texmapOnDisplace = origMtl.texmap_displacement_on |
|
) |
|
|
|
r |
|
), |
|
|
|
— The inputMaterial is expected to be VrayOverrideMtl (checked by an assert). |
|
fn convertVRayOverrideMtlToCoronaRaySwitchMtl inputMaterial =( |
|
assert ((classof inputMaterial) == VrayOverrideMtl) |
|
|
|
local outputMaterial = CoronaRaySwitchMtl() |
|
outputMaterial.name = inputMaterial.name |
|
|
|
outputMaterial.directMtl = inputMaterial.baseMtl |
|
|
|
if inputMaterial.giMtl == undefined then ( |
|
outputMaterial.giMtl = inputMaterial.baseMtl |
|
) else ( |
|
outputMaterial.giMtl = inputMaterial.giMtl |
|
) |
|
|
|
if inputMaterial.reflectMtl == undefined then ( |
|
outputMaterial.reflectMtl = inputMaterial.baseMtl |
|
) else ( |
|
outputMaterial.reflectMtl = inputMaterial.reflectMtl |
|
) |
|
|
|
if inputMaterial.refractMtl == undefined then ( |
|
outputMaterial.refractMtl = inputMaterial.baseMtl |
|
) else ( |
|
outputMaterial.refractMtl = inputMaterial.refractMtl |
|
) |
|
|
|
/*return*/ outputMaterial |
|
), |
|
|
|
— Returns the material being wrapped. If no material is being wrapped, default |
|
— CoronaPhysicalMtl is returned. Otherwise the inputMaterial is returned without any |
|
— modifications. |
|
— The inputMaterial is expected to be VrayMtlWrapper (checked by an assert). |
|
fn unwrapVRayMtlWrapper inputMaterial =( |
|
assert ((classof inputMaterial) == VrayMtlWrapper) |
|
|
|
local outputMaterial = inputMaterial.baseMtl |
|
|
|
if outputMaterial == undefined then ( |
|
outputMaterial = createDefaultCoronaPhysicalMtl inputMaterial.name |
|
) |
|
|
|
/*return*/ outputMaterial |
|
), |
|
|
|
— Returns the material affected by the bump effect. If no material is being affected, default |
|
— CoronaPhysicalMtl is returned. Otherwise the inputMaterial is returned without any |
|
— modifications. |
|
— The inputMaterial is expected to be VRayBumpMtl (checked by an assert). |
|
fn unwrapVRayBumpMtl inputMaterial =( |
|
assert ((classof inputMaterial) == VRayBumpMtl) |
|
|
|
local outputMaterial = inputMaterial.base_mtl |
|
|
|
if outputMaterial == undefined do ( |
|
outputMaterial = createDefaultCoronaPhysicalMtl inputMaterial.name |
|
) |
|
|
|
/*return*/ outputMaterial |
|
|
|
), |
|
|
|
fn convertFrom_Architectural origMtl =( |
|
r = CoronaLegacyMtl() |
|
r.name = origMtl.name |
|
|
|
—Diffuse |
|
r.levelDiffuse = 1.0 |
|
r.colorDiffuse = origMtl.Diffuse |
|
r.texmapDiffuse = origMtl.diffuseMap |
|
if r.texmapDiffuse != undefined then ( |
|
r.texmapOnDiffuse = origMtl.diffuseMapEnable |
|
r.mapamountDiffuse = origMtl.diffuseMapAmount |
|
) |
|
|
|
—Bumpmap |
|
r.texmapBump = origMtl.bumpMap |
|
if r.texmapBump != undefined then ( |
|
r.texmapOnBump = origMtl.bumpMapEnable |
|
r.mapamountBump = origMtl.bumpMapAmount / 100.0 |
|
) |
|
|
|
—Opacity |
|
r.levelOpacity = 1.0 |
|
r.colorOpacity = white |
|
r.texmapOpacity = origMtl.cutoutMap |
|
if r.texmapOpacity != undefined then ( |
|
r.texmapOnOpacity = origMtl.cutoutMapEnable |
|
r.mapamountOpacity = origMtl.cutoutMapAmount —/ 100.0 |
|
) |
|
|
|
r |
|
), |
|
|
|
fn clamp value minimum maximum =( |
|
/*return*/ amin #((amax #(value, minimum)), maximum) |
|
), |
|
|
|
— The inputMaterial is expected to be Shellac (checked by an assert). |
|
fn convertShellacToCoronaLayeredMtl inputMaterial =( |
|
assert ((classof inputMaterial) == Shellac) |
|
|
|
local outputMaterial = CoronaLayeredMtl() |
|
outputMaterial.name = inputMaterial.name |
|
|
|
outputMaterial.baseMtl = inputMaterial.shellacMtl1 |
|
outputMaterial.layers[1] = inputMaterial.shellacMtl2 |
|
|
|
local MINIMUM = 0.0 |
|
local MAXIMUM = 100.0 |
|
outputMaterial.amounts[1] = clamp inputMaterial.shellacColorBlend MINIMUM MAXIMUM |
|
|
|
— Disable unnecessary layers. |
|
for index = 2 to outputMaterial.layers.count do ( |
|
outputMaterial.layersOn[index] = false |
|
) |
|
|
|
/*return*/ outputMaterial |
|
), |
|
|
|
— By Michiel Quist, 3diee.nl |
|
fn convertFrom_iray_Material origMtl =( |
|
r = CoronaLegacyMtl() |
|
r.name = origMtl.name |
|
|
|
—Diffuse |
|
r.levelDiffuse = origMtl.Diffuse_weight |
|
r.colorDiffuse = (color origMtl.diffuse_color.r origMtl.diffuse_color.g origMtl.diffuse_color.b) — is not converting rgba colors, therefore r,g,b seperation |
|
r.texmapDiffuse = origMtl.diffuse_color_map |
|
if r.texmapDiffuse != undefined then ( |
|
r.texmapOnDiffuse = origMtl.enable_diffuse_color_map |
|
) |
|
|
|
—Reflection |
|
r.levelReflect = origMtl.glossy_weight |
|
r.colorReflect = (color origMtl.glossy_color.r origMtl.glossy_color.g origMtl.glossy_color.b) |
|
r.texmapReflect = origMtl.glossy_color_map |
|
if r.texmapReflect != undefined then ( |
|
r.texmapOnReflect = origMtl.Enable_glossy_color_map |
|
) |
|
r.fresnelIor = 999.0 |
|
r.texmapFresnelIor = origMtl.Fresnel_IOR_map |
|
if r.texmapFresnelIor != undefined then ( |
|
r.texmapOnFresnelIor = origMtl.enable_Fresnel_IOR_map — only active when global ior map on and brdf radiobutton set to «by IOR» |
|
) |
|
r.reflectGlossiness = 1 — origMtl.Glossy_roughness |
|
r.texmapReflectGlossiness = origMtl.Glossy_roughness_map |
|
if r.texmapReflectGlossiness != undefined then ( |
|
r.texmapOnReflectGlossiness = origMtl.enable_Glossy_roughness_map |
|
) |
|
|
|
—Refraction |
|
if origMtl.Enable_refraction == on then ( |
|
r.levelRefract = 1 |
|
r.ior = if origMtl.refraction_ior < 1.0 then ( |
|
1.0 |
|
) else ( |
|
if origMtl.refraction_ior > 10.0 then ( |
|
10.0 |
|
) else ( |
|
origMtl.refraction_ior |
|
) |
|
) |
|
r.fresnelIor = r.ior |
|
r.colorRefract = r.colorReflect |
|
) |
|
|
|
— Glassmode |
|
if origMtl.Thin_material == 1 then ( |
|
r.thin = true |
|
) |
|
|
|
—Translucency |
|
if origMtl.Enable_translucency == false then ( |
|
r.levelTranslucency = 0.0 |
|
) else ( |
|
—r.levelTranslucency = origMtl.refr_transw |
|
r.levelTranslucency = origMtl.Translucency_weight |
|
r.levelRefract = (origMtl.refraction_ior) |
|
) |
|
r.colorTranslucency = (color origMtl.translucency_color.r origMtl.translucency_color.g origMtl.translucency_color.b) |
|
r.texmapTranslucency = origMtl.Translucency_color_map |
|
if r.texmapTranslucency != undefined then ( |
|
r.texmapOnTranslucency = origMtl.enable_Translucency_color_map |
|
) |
|
|
|
—Opacity |
|
r.levelOpacity = 1.0 |
|
r.colorOpacity = white |
|
r.texmapOpacity = origMtl.cutout_map |
|
if r.texmapOpacity != undefined then ( |
|
r.texmapOnOpacity = origMtl.enable_cutout |
|
) |
|
|
|
—Emission |
|
if hasproperty origMtl «Enable_emission« then ( |
|
if origMtl.Enable_emission then ( |
|
r.levelSelfIllum = origMtl.luminance / 100 |
|
) |
|
) |
|
r.colorSelfIllum = (color origMtl.filter_Color.r origMtl.filter_Color.g origMtl.filter_Color.b) |
|
r.texmapSelfIllum = origMtl.Filter_color_map |
|
if r.texmapSelfIllum != undefined then ( |
|
r.texmapOnSelfIllum = origMtl.Enable_filter_color_map |
|
) |
|
|
|
—Bumpmap |
|
if hasproperty origMtl «Base_bump_map« then ( |
|
r.texmapBump = origMtl.Base_bump_map |
|
if r.texmapBump != undefined then ( |
|
r.texmapOnBump = origMtl.Enable_base_bump_map |
|
r.mapamountBump = origMtl.Base_bump_map_amount * VRAY_BUMP_MULTIPLIER |
|
) |
|
) |
|
|
|
—Anisotropy |
|
if origMtl.Enable_base_forward then ( |
|
r.anisotropy = origMtl.Base_forward_amount |
|
r.texmapReflectAnisotropy = origMtl.Base_forward_amount_map |
|
if r.texmapReflectAnisotropy != undefined then ( |
|
r.texmapOnAnisotropy = origMtl.Base_forward_amount_map_enabled |
|
) |
|
r.anisotropyRotation = origMtl.Base_rotation |
|
r.texmapReflectAnisotropyRotation = origMtl.Base_rotation_map |
|
if r.texmapReflectAnisotropyRotation != undefined then ( |
|
r.texmapOnAnisotropyRotation = origMtl.Base_rotation_map_enabled |
|
) |
|
) |
|
|
|
—Displacement |
|
r.texmapDisplace = origMtl.displacement_map |
|
if r.texmapDisplace != undefined then ( |
|
r.texmapOnDisplacement = origMtl.Enable_displacement |
|
) |
|
|
|
—Volume settings like absorption and SSS no dispersion and thin film yet |
|
if origMtl.Enable_absorption and origMtl.Thin_material == 0 then ( |
|
r.absorptionDistance = origMtl.Volume_distance |
|
r.absorptionColor = (color origMtl.Transmitted_color.r origMtl.Transmitted_color.g origMtl.Transmitted_color.b) |
|
|
|
if origMtl.Enable_SSS then ( |
|
r.scatterColor = (color (white * origMtl.SSS_amount).r (white * origMtl.SSS_amount).g (white * origMtl.SSS_amount).b) |
|
r.scatterDirectionality = origMtl.SSS_direction |
|
) |
|
) |
|
|
|
—Lets see if it has a reflective coating and then create a coronalayered material.. |
|
if (hasproperty origMtl «Enable_reflective_coating«) and origMtl.Enable_reflective_coating then ( |
|
quiz = CoronaLayeredMtl() |
|
refcoat = CoronaLegacyMtl() |
|
refcoat.name = r.name + «_coating« |
|
quiz.name = r.name + «_layer« |
|
r.name = r.name + «_base« |
|
|
|
—coating values s variable!! |
|
refcoat.levelDiffuse = 0.0 |
|
refcoat.colorDiffuse = black |
|
|
|
refcoat.levelReflect = 1.0 |
|
refcoat.colorReflect = (color origMtl.color.r origMtl.color.g origMtl.color.b) |
|
refcoat.texmapReflect = origMtl.color_Map |
|
if refcoat.texmapReflect != undefined then ( |
|
refcoat.texmapOnReflect = origMtl.Enable_color_map |
|
) |
|
if origMtl.Blend_mode == 0 then ( |
|
refcoat.fresnelIor = 999.0 |
|
) |
|
if origMtl.Blend_mode == 1 then ( |
|
refcoat.fresnelIor = origMtl.Fresnel_IOR |
|
) |
|
if origMtl.Blend_mode == 2 then ( |
|
refcoat.fresnelIor = origMtl.Fresnel_IOR |
|
) |
|
refcoat.texmapFresnelIor = origMtl.weight_map |
|
if refcoat.texmapFresnelIor != undefined then ( |
|
refcoat.texmapOnFresnelIor = origMtl.Enable_weight_map — only active when global ior map on and brdf radiobutton set to «by IOR» |
|
) |
|
refcoat.reflectGlossiness = 1 — origMtl.roughness |
|
refcoat.texmapReflectGlossiness = origMtl.roughness_map |
|
if refcoat.texmapReflectGlossiness != undefined then ( |
|
refcoat.texmapOnReflectGlossiness = origMtl.enable_roughness_map |
|
) |
|
|
|
—Bumpmap |
|
refcoat.texmapBump = origMtl.bump_map |
|
if refcoat.texmapBump != undefined then ( |
|
refcoat.texmapOnBump = origMtl.enable_bump_map |
|
refcoat.mapamountBump = origMtl.bump_map_amount * VRAY_BUMP_MULTIPLIER |
|
) |
|
|
|
—construct the layered material |
|
quiz.baseMtl = r |
|
|
|
quiz.layers[1] = refcoat |
|
|
|
if origMtl.Blend_mode == 0 then ( |
|
quiz.amounts[1] = origMtl.weight * 100 |
|
) |
|
if origMtl.Blend_mode == 1 or origMtl.Blend_mode == 2 then ( |
|
quiz.amounts[1] = origMtl.weight * 100 |
|
fall = falloff() |
|
fall.name = r.name + «_falloff« |
|
fall.type = 2 |
|
fall.mtlIOROverride = on |
|
fall.ior = origMtl.Fresnel_IOR |
|
|
|
quiz.mixmaps[1] = fall |
|
) |
|
r = quiz |
|
) |
|
|
|
r |
|
) |
|
) |
|
matConvMethods owner:this |
|
), |
|
|
|
mapConvMethods =( |
|
struct mapConvMethods ( |
|
owner, |
|
|
|
fn convertFrom_BitmapTexture origMap =( |
|
assert ((classof origMap) == Bitmaptexture) |
|
|
|
r = CoronaBitmap() |
|
r.name = origMap.name |
|
doNotConvert = false |
|
|
|
— filename, output |
|
if origMap.fileName != «« and origMap.fileName != undefined then ( |
|
type = getFilenameType origMap.fileName |
|
if (findItem #(«.jpg«, «.jpeg«, «.png«, «.gif«, «.bmp«, «.exr«, «.psd«, «.tif«, «.tiff«, «.tga«, «.hdr«) (toLower type)) != 0 then ( |
|
r.filename = origMap.fileName |
|
|
|
— gamma handling, ONLY max 2014+ |
|
local isValidMap = true |
|
try ( |
|
origMap.bitmap |
|
) catch (isValidMap = false) |
|
|
|
if (maxVersion())[1] >= 16000 and isValidMap then ( |
|
local gammaOrig = origMap.bitmap.inputGamma |
|
if classof gammaOrig == Float do ( |
|
r.gamma = gammaOrig |
|
) |
|
) |
|
) else ( |
|
doNotConvert = true |
|
) |
|
) else ( |
|
r.filename = «« |
|
—doNotConvert = true |
|
) |
|
r.output = copy origMap.output |
|
|
|
if origMap.coords.mappingType == MAPPING_TYPE_ENVIRONMENT then ( |
|
case origMap.coords.mapping of ( |
|
BITMAP_MAPPING_SPHERICAL: r.enviroMapping = CORONA_BITMAP_MAPPING_SPHERICAL |
|
BITMAP_MAPPING_SCREEN: r.enviroMapping = CORONA_BITMAP_MAPPING_SCREEN |
|
default: () — CoronaBitmap does not support neither cylindrical nor shrink-wrap mapping. |
|
) |
|
) |
|
|
|
r.uvwChannel = origMap.coords.mapChannel |
|
|
|
if origMap.coords.mappingType == MAPPING_TYPE_TEXTURE and origMap.coords.mapping == BITMAP_MAPPING_VERTEX_COLOR_CHANNEL then ( |
|
r.uvwChannel = 0 |
|
) |
|
|
|
— blur |
|
r.filteringBlur = origMap.coords.blur |
|
|
|
— alpha source, mono channel out, rgb channel out |
|
r.alphaSource = origMap.alphaSource |
|
r.monoChannelOutput = origMap.monoOutput |
|
r.rgbChannelOutput = origMap.rgbOutput |
|
|
|
— offset, tiling/scale, rotation, rw mapscale |
|
r.realWorldScale = origMap.coords.realWorldScale |
|
r.uvwOffset = [origMap.coords.U_Offset, origMap.coords.V_Offset, 0] |
|
if r.realWorldScale then ( |
|
r.uvwScale = [origMap.coords.realWorldWidth, origMap.coords.realWorldHeight, 1] |
|
) else ( |
|
r.uvwScale = [origMap.coords.U_Tiling, origMap.coords.V_Tiling, 1] |
|
) |
|
|
|
uM = origMap.coords.U_Mirror |
|
uT = origMap.coords.U_Tile |
|
case tileChkU of ( |
|
(uM == false and uT == false): r.tilingU = 0 |
|
(uM == true and uT == false): r.tilingU = 2 |
|
(uM == false and uT == true): r.tilingU = 1 |
|
) |
|
vM = origMap.coords.V_Mirror |
|
vT = origMap.coords.V_Tile |
|
case tileChkV of ( |
|
(vM == false and vT == false): r.tilingV = 0 |
|
(vM == true and vT == false): r.tilingV = 2 |
|
(vM == false and vT == true): r.tilingV = 1 |
|
) |
|
r.wAngle = origMap.coords.W_angle |
|
|
|
— crop/place |
|
r.clippingOn = origMap.apply |
|
r.clippingMode = origMap.cropPlace |
|
r.clippingU = origMap.clipu |
|
r.clippingV = origMap.clipv |
|
r.clippingWidth = origMap.clipw |
|
r.clippingHeight = origMap.cliph |
|
|
|
if doNotConvert then ( |
|
r = #NoReplacement |
|
) |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_VrayHDRI origMap =( |
|
r = BitmapTexture() |
|
r.name = origMap.name |
|
doNotConvert = false |
|
|
|
— filename, output |
|
if origMap.HDRIMapName != «« and origMap.HDRIMapName != undefined then ( |
|
—doNotConvert = true |
|
r.fileName = origMap.HDRIMapName |
|
) |
|
|
|
r.output = copy origMap.Output |
|
if hasproperty origMap #coords then ( |
|
r.coords = origMap.coords |
|
) |
|
|
|
— Gamma handling |
|
if (maxversion())[1] >= 16000 and origMap.gamma != 1 then ( |
|
try ( |
|
r.bitmap = openBitmap r.bitmap.filename gamma:(1.0 / origMap.gamma) |
|
) catch () |
|
) |
|
|
|
if origMap.mapType == 2 then ( — Spherical mode |
|
r.coords.mapping = BITMAP_MAPPING_SPHERICAL |
|
r.coords.mappingType = MAPPING_TYPE_ENVIRONMENT |
|
r.coords.U_Offset = 0.25 + origMap.horizontalRotation / 360.0 |
|
r.coords.V_Offset = origMap.verticalRotation / 180.0 |
|
|
|
if origMap.horizontalFlip then ( |
|
r.coords.U_Offset = 0.25 — origMap.horizontalRotation / 360.0 |
|
r.coords.U_Tiling = —r.coords.U_Tiling |
|
) |
|
if origMap.verticalFlip then ( |
|
r.coords.V_Tiling = —r.coords.V_Tiling |
|
) |
|
) |
|
|
|
— alpha source, mono channel out, rgb channel out |
|
r.alphaSource = origMap.alphaSource |
|
r.monoOutput = origMap.monoOutput |
|
|
|
r.rgbOutput = if origMap.rgbOutput > 1 then ( |
|
0 |
|
) else ( |
|
origMap.rgbOutput |
|
) |
|
|
|
— crop/place |
|
r.apply = origMap.cropplace_on |
|
r.cropPlace = origMap.cropplace_mode |
|
r.clipu = origMap.cropplace_u |
|
r.clipv = origMap.cropplace_v |
|
r.clipw = origMap.cropplace_width |
|
r.cliph = origMap.cropplace_height |
|
|
|
r.output.output_amount *= origMap.multiplier * origMap.renderMultiplier |
|
|
|
if doNotConvert then ( |
|
r = #NoReplacement |
|
) |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_CoronaBitmap origMap =( |
|
assert ((classof origMap) == CoronaBitmap) |
|
|
|
r = Bitmaptexture() |
|
r.name = origMap.name |
|
doNotConvert = false |
|
|
|
— filename, output |
|
if origMap.filename != «« and origMap.filename != undefined then ( |
|
r.fileName = origMap.filename |
|
|
|
— gamma handling, ONLY max 2014+ |
|
if (maxVersion())[1] >= 16000 then ( |
|
local gammaOrig = origMap.gamma |
|
if gammaOrig != —1.0 do ( |
|
r.bitmap = openBitmap origMap.filename gamma:gammaOrig |
|
) |
|
) |
|
) else ( |
|
doNotConvert = true |
|
) |
|
r.output = copy origMap.output |
|
|
|
— CoronaBitmap does not have a parameter which controls whether it uses environment or |
|
— UVW mapping. It automatically detects which slot it is connected to and if it’s |
|
— connected to 3ds Max’s environment map or to some material’s environment override slot |
|
— it automatically uses environment mapping, otherwise it uses UVW mapping. Since |
|
— detecting whether this map is connected to some material’s slot via MAXScript is |
|
— difficult, we at least check whether it is connected to 3ds Max’s environment map and |
|
— act accordingly. |
|
if environmentMap == origMap then ( |
|
r.coords.mappingType = MAPPING_TYPE_ENVIRONMENT |
|
|
|
case origMap.enviroMapping of ( |
|
CORONA_BITMAP_MAPPING_SPHERICAL: r.coords.mapping = BITMAP_MAPPING_SPHERICAL |
|
CORONA_BITMAP_MAPPING_SCREEN: r.coords.mapping = BITMAP_MAPPING_SCREEN |
|
default: () — Bitmaptexture does not support neither dome, cross nor mirror ball mapping. |
|
) |
|
) |
|
|
|
if origMap.uvwChannel == 0 then ( |
|
r.coords.mapping = BITMAP_MAPPING_VERTEX_COLOR_CHANNEL |
|
) else ( |
|
r.coords.mapChannel = origMap.uvwChannel |
|
) |
|
|
|
— blur |
|
r.coords.blur = origMap.filteringBlur |
|
|
|
— alpha source, mono channel out, rgb channel out |
|
r.alphaSource = origMap.alphaSource |
|
r.monoOutput = origMap.monoChannelOutput |
|
r.rgbOutput = origMap.rgbChannelOutput |
|
|
|
— offset, tiling/scale, rotation, rw mapscale |
|
r.coords.realWorldScale = origMap.realWorldScale |
|
|
|
r.coords.U_Offset = origMap.uvwOffset[1] |
|
r.coords.V_Offset = origMap.uvwOffset[2] |
|
|
|
if origMap.realWorldScale then ( |
|
r.coords.realWorldWidth = origMap.uvwScale[1] |
|
r.coords.realWorldHeight = origMap.uvwScale[2] |
|
) else ( |
|
r.coords.U_Tiling = origMap.uvwScale[1] |
|
r.coords.V_Tiling = origMap.uvwScale[2] |
|
) |
|
|
|
case origMap.tilingU of ( |
|
0: (r.coords.U_Mirror = false; r.coords.U_Tile = false) |
|
2: (r.coords.U_Mirror = true; r.coords.U_Tile = false) |
|
1: (r.coords.U_Mirror = false; r.coords.U_Tile = true) |
|
) |
|
case origMap.tilingV of ( |
|
0: (r.coords.V_Mirror = false; r.coords.V_Tile = false) |
|
2: (r.coords.V_Mirror = true; r.coords.V_Tile = false) |
|
1: (r.coords.V_Mirror = false; r.coords.V_Tile = true) |
|
) |
|
r.coords.W_angle = origMap.wAngle |
|
|
|
— crop/place |
|
r.apply = origMap.clippingOn |
|
r.cropPlace = origMap.clippingMode |
|
r.clipu = origMap.clippingU |
|
r.clipv = origMap.clippingV |
|
r.clipw = origMap.clippingWidth |
|
r.cliph = origMap.clippingHeight |
|
|
|
if doNotConvert then ( |
|
r = #NoReplacement |
|
) |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_VrayColor origMap =( |
|
r = CoronaColor() |
|
r.name = origMap.name |
|
|
|
r.color = origMap.color |
|
r.name = origMap.name |
|
r.multiplier = origMap.rgb_multiplier |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_VrayDirt origMap =( |
|
r = CoronaAo() |
|
r.name = origMap.name |
|
|
|
fn validate val =( |
|
val = val / 10.0 |
|
|
|
if val < —10.0 then ( |
|
/*return*/ —10.0 |
|
) else if val > 10.0 then ( |
|
/*return*/ 10.0 |
|
) else ( |
|
/*return*/ val |
|
) |
|
) |
|
|
|
r.colorOccluded = origMap.occluded_color |
|
r.colorUnoccluded = origMap.unoccluded_color |
|
r.maxDistance = origMap.radius |
|
|
|
if origMap.invert_normal then ( |
|
r.normalMode = 1 |
|
) else ( |
|
r.normalMode = 0 |
|
) |
|
r.texmapDistance = origMap.texmap_radius |
|
r.texmapOccluded = origMap.texmap_occluded_color |
|
r.texmapUnoccluded = origMap.texmap_unoccluded_color |
|
r.excludeMode = 0 |
|
|
|
r.directionOffsets = [validate origMap.bias.x, validate origMap.bias.y, validate origMap.bias.z] |
|
|
|
if origMap.includeList != undefined and origMap.includeList.count != 0 then ( |
|
r.includeMod = true |
|
r.excludeList = origMap.includeList |
|
r.excludeMode = 1 |
|
) |
|
if origMap.excludeList != undefined and origMap.excludeList.count != 0 then ( |
|
r.includeMod = false |
|
r.excludeList = origMap.excludeList |
|
r.excludeMode = 1 |
|
) |
|
if origMap.consider_same_object_only then ( |
|
r.excludeMode = 3 |
|
) |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_Ambient_Reflective_Occlusion__3dsmax origMap =( |
|
r = CoronaAo() |
|
r.name = origMap.name |
|
|
|
r.colorOccluded = origMap.dark |
|
r.colorUnoccluded = origMap.bright |
|
r.maxDistance = origMap.max_distance |
|
|
|
if origMap.output_mode == 5 then ( |
|
r.normalMode = 1 |
|
) else ( |
|
r.normalMode = 0 |
|
) |
|
r.texmapDistance = origMap.max_distance_shader |
|
r.texmapOccluded = origMap.dark_shader |
|
r.texmapUnoccluded = origMap.bright_shader |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_Normal_Bump origMap =( |
|
r = CoronaNormal() |
|
r.name = origMap.name |
|
|
|
r.multiplier = origMap.mult_spin |
|
r.normalMap = origMap.normal_map |
|
|
|
r.flipRed = origMap.flipRed |
|
r.flipGreen = origMap.flipGreen |
|
r.swapRedGreen = origMap.swap_rg |
|
|
|
r.additionalBump = origMap.bump_map |
|
r.additionalBumpOn = origMap.map2on |
|
r.additionalBumpStrength = origMap.bump_spin |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_VrayNormalMap origMap =( |
|
r = CoronaNormal() |
|
r.name = origMap.name |
|
|
|
r.multiplier = 1.0 |
|
r.normalMap = origMap.normal_map |
|
|
|
if hasproperty origMap #flip_red then ( |
|
r.flipred = origMap.flip_red |
|
r.flipgreen = origMap.flip_green |
|
r.swapRedGreen = origMap.swap_red_and_green |
|
) |
|
|
|
if hasProperty origMap #bump_map then ( — V-Ray 3.3 |
|
r.additionalBump = origMap.bump_map |
|
if r.additionalBump != undefined do ( |
|
r.additionalBumpOn = origMap.bump_map_on |
|
r.additionalBumpStrength = origMap.bump_map_multiplier * VRAY_BUMP_MULTIPLIER |
|
) |
|
) |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_VraySky origMap =( |
|
r = CoronaSky() |
|
r.name = origMap.name |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_VRayCompTex origMap =( |
|
r = CoronaMix() |
|
r.name = origMap.name |
|
|
|
r.texmapBottom = origMap.sourceA |
|
r.texmapTop = origMap.sourceB |
|
r.mixOperation = case origMap.operator of ( |
|
0: 0 — Add |
|
1: 1 — Subtract |
|
2: 8 — Difference |
|
3: 2 — Multiply |
|
4: 3 — Divide |
|
5: 4 — Minimum |
|
6: 5 — Maximum |
|
default:0 |
|
) |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_VRayEdgesTex origMap =( |
|
r = CoronaWire() |
|
r.name = origMap.name |
|
|
|
r.edgeColor = origMap.edgesColor |
|
r.widthMode = (abs (origMap.widthType — 1)) |
|
r.edgeWidthWorld = origMap.thickness |
|
r.edgeWidthPixels = origMap.pixelWidth |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_VRayTriplanarTex origMap =( |
|
r = CoronaTriplanar() |
|
r.name = origMap.name |
|
|
|
r.scale = 1.0 / origMap.scale |
|
if origMap.texture_mode == 0 then ( — Same texture on all axes. |
|
r.onlyTexmapX = true |
|
r.texmapX = origMap.texture |
|
) else ( |
|
r.onlyTexmapX = false |
|
r.texmapX = origMap.texture |
|
r.texmapY = origMap.texture_y |
|
r.texmapZ = origMap.texture_z |
|
) |
|
|
|
r.blend = origMap.blend |
|
r.offset = origMap.frame_offset |
|
r.rotation = origMap.texture_rotation |
|
|
|
case origMap.space of ( |
|
0: r.space = 0 |
|
1: ( |
|
r.space = 2 |
|
r.referenceNode = origMap.reference_node |
|
) |
|
) |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_VRayGLSLTex origMap =( |
|
r = CoronaColor() |
|
r.name = origMap.name |
|
|
|
r.color = (color 127 127 127) |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_VRaySoftbox origMap =( |
|
r = CoronaColor() |
|
r.name = origMap.name |
|
|
|
r.color = white |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_VRayColor2Bump origMap =( |
|
r = CoronaBumpConverter() |
|
r.name = origMap.name |
|
|
|
r.input = origMap.map |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_Autodesk_Map origMap =( |
|
r |
|
if hasProperty origMap «Parameters_Source« then ( |
|
r = Bitmaptexture() |
|
r.name = origMap.name |
|
|
|
try ( — Whacky, need bug test scene to solve further issues. |
|
r.bitmap = origMap.Parameters_Source |
|
) catch () |
|
r.coords.realWorldScale = true |
|
r.coords.realWorldWidth = origMap.Scale_Width —/ 100 |
|
r.coords.realWorldHeight = origMap.Scale_Height —/ 100 |
|
—r.coords.U_Offset = origMap.Position_X — Broken in Autodesk maps. |
|
—r.coords.V_Offset = origMap.Position_Y — Broken in Autodesk maps. |
|
|
|
r.coords.U_Tile = origMap.Repeat_Horizontal |
|
r.coords.V_Tile = origMap.Repeat_Vertical |
|
r.coords.mapChannel = origMap.Advanced_Parameters_Map_Channel |
|
) else ( |
|
r = CoronaColor() |
|
r.name = origMap.name |
|
r.color = (color 127 127 127) |
|
) |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_Multi_Sub_Map origMap =( |
|
r = CoronaMultiMap() |
|
r.name = origMap.name |
|
|
|
r.items = origMap.num_colors + 1 |
|
r.mode = case origMap.mode of ( |
|
0: 5 — ObjectID |
|
1: 3 — Material ID |
|
2: 5 — Smoothing group does not exist in Corona -> ObjectID |
|
3: 2 — Random -> Instance |
|
default: 5 |
|
) |
|
|
|
if r.mode == 5 then ( |
|
r.items = origMap.num_colors + 1 |
|
r.texmaps[1] = origMap.id_out_of_range_color_shader |
|
r.colors[1] = origMap.id_out_of_range_color |
|
for i = 0 to origMap.num_colors — 1 do ( |
|
r.texmaps[i + 2] = getProperty origMap («id_« + i as string + «_color_shader«) |
|
r.colors[i + 2] = getProperty origMap («id_« + i as string + «_color«) |
|
) |
|
) else ( |
|
r.items = origMap.num_colors |
|
for i = 0 to origMap.num_colors — 1 do ( |
|
r.texmaps[i + 1] = getProperty origMap («id_« + i as string + «_color_shader«) |
|
r.colors[i + 1] = getProperty origMap («id_« + i as string + «_color«) |
|
) |
|
) |
|
|
|
r |
|
) |
|
) |
|
mapConvMethods owner:this |
|
), |
|
|
|
lightConvMethods =( |
|
struct lightConvMethods ( |
|
owner, |
|
|
|
fn convertFrom_VrayLight origLight =( |
|
r = CoronaLight intensityUnits:0 |
|
r.name = (if owner.converterSettings.addCoronaPrefix then ( |
|
owner.converterSettings.userPrefixStr |
|
) else ( |
|
«« |
|
)) + origLight.name |
|
doNotConvert = false |
|
|
|
— OnOff, Include/exclude |
|
r.on = origLight.on |
|
r.targeted = origLight.targeted |
|
case of ( |
|
(origLight.includeList != undefined and origLight.includeList.count != 0): ( |
|
r.excludeIncludeMod = true |
|
r.excludeList = origLight.includeList |
|
) |
|
(origLight.excludeList != undefined and origLight.excludeList.count != 0): ( |
|
r.excludeIncludeMod = false |
|
r.excludeList = origLight.excludeList |
|
) |
|
default: () |
|
) |
|
|
|
— Corona: 0: Default W/(sr .m^2), 1: Lumen(lm), 2: candela (cd), 3:Lux (lx) |
|
— Vray: 0: Default (image), 1 : luminous (lm), 2: lumincance (lm/m^2/sr), 3: radiant power (w), 4: radiance (w/m^2/sr) |
|
|
|
case origLight.normalizeColor of ( |
|
0: ( — vray default (image) |
|
r.intensity = origLight.multiplier |
|
) |
|
1: ( — vray luminous (lm) |
|
r.intensityUnits = 1 — corona lumen |
|
r.intensity = origLight.multiplier |
|
) |
|
2: ( — vray luminance (lm/m^2/sr) |
|
r.intensityUnits = 0 — corona default |
|
r.intensity = origLight.multiplier / 683.0 —/ 477.465 |
|
) |
|
3: ( — vray radiant power (w) |
|
r.intensityUnits = 1 — corona lumen |
|
r.intensity = origLight.multiplier * 683.0 |
|
) |
|
4: ( — vray radiance (w/m^2/sr) |
|
r.intensityUnits = 0 — corona default |
|
r.intensity = origLight.multiplier — / 0.699 |
|
) |
|
) |
|
|
|
r.colorMode = origLight.color_mode — 0: direct color, 1: kelvin temp, 2: texmap |
|
r.color = origLight.color |
|
if r.colorMode == 1 do ( |
|
r.blackbodyTemp = origLight.color_temperature — kelvin |
|
) |
|
if origLight.texmap_on and origLight.texmap != undefined do ( |
|
r.colorMode = 2 |
|
r.texmap = origLight.texmap |
|
) |
|
|
|
fn getCoronaDirectionality lightDistribution curve =( |
|
for dataPoint in curve do ( |
|
if ((dataPoint.x * 100.0) as integer) == ((lightDistribution * 100.0) as integer) then ( |
|
return dataPoint.y |
|
) |
|
) |
|
|
|
/*return*/ lightDistribution |
|
) |
|
|
|
—r.directionality = logit origLight.lightDistribution 10 |
|
r.directionality = getCoronaDirectionality origLight.lightDistribution owner.converterSettings.VRAY_DIRECTIONALITY_TO_CORONA_DIRECTIONALITY |
|
|
|
— visibility |
|
r.twosidedEmission = origLight.DoubleSided |
|
r.visibleDirectly = not origLight.invisible |
|
r.visibleRefl = origLight.affect_reflections |
|
r.occludeOtherLights = origLight.castShadows |
|
|
|
— Shape: 0: Plane, 1: Dome, 2: Sphere, 3: Mesh, 4: Disc |
|
case origLight.type of ( |
|
0: ( r.shape = 1 — Plane |
|
r.width = origLight.size0 * 2.0 |
|
r.height = origLight.size1 * 2.0 |
|
|
|
if origLight.skylightPortal then ( |
|
— Corona Renderer does not support light portals anymore. |
|
doNotConvert = true |
|
) |
|
) |
|
1: doNotConvert = true — Dome |
|
2: ( |
|
r.shape = 0 — Sphere |
|
r.width = origLight.size0 |
|
) |
|
3: ( — Mesh |
|
if hasproperty origLight #Shape_mesh do ( |
|
if origLight.skylightPortal then ( |
|
— Corona Renderer does not support light portals anymore. |
|
|
|
) else ( |
|
— CoronaLight can not be «represented» by a mesh while VRayLight can. |
|
— Therefore we extract the mesh of VRayLight and assign it CoronaLightMtl |
|
— with the same parameters as the VRayLight. |
|
local mtl = CoronaLightMtl() |
|
mtl.color = origLight.color |
|
mtl.intensity = origLight.multiplier |
|
mtl.texmapOn = origLight.texmap_on |
|
mtl.texmap = origLight.texmap |
|
mtl.emitLight = origLight.on |
|
mtl.twosidedEmission = origLight.DoubleSided |
|
mtl.occludeOther = origLight.castShadows |
|
mtl.visibleDirect = not origLight.invisible |
|
mtl.visibleRefl = origLight.affect_reflections |
|
|
|
delete r |
|
r = copy origLight |
|
r.baseobject = r.Shape_mesh |
|
|
|
InstanceMgr.GetInstances origLight &rptInstances |
|
trueInstances = for n in rptInstances where (areNodesInstances origLight n) collect n |
|
|
|
for i in trueInstances do ( |
|
instanceReplace i r |
|
) |
|
|
|
trueInstances.material = mtl |
|
) |
|
) |
|
doNotConvert = true |
|
) |
|
4: ( |
|
r.shape = 2 — Disc |
|
r.width = origLight.size0 |
|
) |
|
) |
|
|
|
if doNotConvert then ( |
|
delete r |
|
r = #NoReplacement |
|
) |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_StandardLights origLight =( |
|
crnShd = CoronaShadows() |
|
useAS |
|
asRad |
|
|
|
if (classof origLight.shadowgenerator) == VRayShadow do ( |
|
useAS = origLight.AreaShadow |
|
asRad = origLight.usize |
|
) |
|
|
|
if (classof origLight.shadowgenerator) != CoronaShadows do ( |
|
origLight.shadowgenerator = crnShd |
|
|
|
if useAS != undefined do ( |
|
origLight.areaShadows = useAS |
|
) |
|
if asRad != undefined do ( |
|
origLight.areaRadius = asRad |
|
) |
|
) |
|
|
|
origLight |
|
), |
|
|
|
fn convertFrom_miAreaLight origLight =( |
|
if owner.converterSettings.miLightsToCrnLights then ( — Convert to CoronaLight(s). |
|
r = CoronaLight() |
|
r.name = (if owner.converterSettings.addCoronaPrefix then ( |
|
owner.converterSettings.userPrefixStr |
|
) else ( |
|
«« |
|
)) + origLight.name |
|
|
|
r.on = origLight.on |
|
try ( |
|
r.targeted = origLight.targeted |
|
) catch () |
|
|
|
case of ( |
|
(origLight.includeList != undefined and origLight.includeList.count != 0): ( |
|
r.excludeIncludeMod = true |
|
r.excludeList = origLight.includeList |
|
) |
|
(origLight.excludeList != undefined and origLight.excludeList.count != 0): ( |
|
r.excludeIncludeMod = false |
|
r.excludeList = origLight.excludeList |
|
) |
|
default: () |
|
) |
|
|
|
r.intensity = origLight.multiplier |
|
r.colorMode = 0 |
|
r.color = origLight.rgb |
|
|
|
if origLight.Area_Enable then ( |
|
case (classof origLight) of ( |
|
miAreaLight:( |
|
case origLight.Area_Type of ( |
|
1:( r.shape = 1 — Rectangle |
|
r.width = origLight.Rectangle_Width |
|
r.height = origLight.Rectangle_Height |
|
) |
|
2:( r.shape = 2 — Disc |
|
r.width = origLight.Disc_Radius |
|
) |
|
) |
|
) |
|
miAreaLightomni:( |
|
case origLight.Area_Type of ( |
|
1:( r.shape = 0 — Sphere |
|
r.width = origLight.Sphere_Radius |
|
) |
|
2:( r.shape = 3 — Cylinder |
|
r.width = origLight.Sphere_Radius |
|
r.height = origLight.Cylinder_Height |
|
) |
|
) |
|
) |
|
default:() |
|
) |
|
) |
|
|
|
r |
|
) else ( — Convert to standard lights. |
|
r |
|
origLight.name = (if owner.converterSettings.addCoronaPrefix then ( |
|
owner.converterSettings.userPrefixStr |
|
) else ( |
|
«« |
|
)) + origLight.name |
|
|
|
case of ( |
|
(hasproperty origLight «Free_Spot«) : r = origLight.Free_Spot |
|
(hasproperty origLight «Target_Spot«) : r = origLight.Target_Spot |
|
(hasproperty origLight «Free_Directional_Light«) : r = origLight.Free_Directional_Light |
|
(hasproperty origLight «Target_Directional_Light«) : r = origLight.Target_Directional_Light |
|
(hasproperty origLight «Omni_Light«) : r = origLight.Omni_Light |
|
default: () |
|
) |
|
|
|
crnShd = CoronaShadows() |
|
crnShd.areaShadows = origLight.Area_Enable |
|
|
|
if origLight.Area_Enable then ( |
|
case (classof origLight) of ( |
|
miAreaLight:( |
|
case origLight.Area_Type of ( |
|
1: crnShd.areaRadius = origLight.Rectangle_Width / 2.0 — Rectangle |
|
2: crnShd.areaRadius = origLight.Disc_Radius — Disc |
|
) |
|
) |
|
miAreaLightomni:( |
|
case origLight.Area_Type of ( |
|
1: crnShd.areaRadius = origLight.Sphere_Radius — Sphere |
|
2: crnShd.areaRadius = origLight.Sphere_Radius — Cylinder |
|
) |
|
) |
|
default:() |
|
) |
|
) |
|
r.shadowgenerator = crnShd |
|
|
|
r |
|
) |
|
|
|
), |
|
|
|
fn convertFrom_fRRectLight origLight =( |
|
r = CoronaLight() |
|
r.name = (if owner.converterSettings.addCoronaPrefix then ( |
|
owner.converterSettings.userPrefixStr |
|
) else ( |
|
«« |
|
)) + origLight.name |
|
doNotConvert = false |
|
|
|
— OnOff, Include/exclude |
|
r.on = origLight.on |
|
r.targeted = origLight.isTargeted |
|
— include exclude is using some freaky fR Sh*t again… will support later |
|
|
|
if origLight.lightPortal != 0 do ( |
|
doNotConvert = true |
|
) |
|
|
|
— Intensitiy, Color, Texmap |
|
r.intensity = origLight.multiplier |
|
r.shape = 1 |
|
r.width = origLight.width |
|
r.height = origLight.length |
|
|
|
r.color = origLight.color |
|
|
|
— visibility |
|
r.visibleDirectly = not origLight.renderIcon |
|
|
|
if doNotConvert then ( |
|
delete r |
|
r = #NoReplacement |
|
) |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_VrayIES origLight =( |
|
r = CoronaLight() |
|
r.name = (if owner.converterSettings.addCoronaPrefix then ( |
|
owner.converterSettings.userPrefixStr |
|
) else ( |
|
«« |
|
)) + origLight.name |
|
|
|
— OnOff, Include/exclude |
|
r.on = origLight.enabled |
|
r.targeted = origLight.targeted |
|
case of ( |
|
(origLight.includeList != undefined and origLight.includeList.count != 0): ( |
|
r.excludeIncludeMod = true |
|
r.excludeList = origLight.includeList |
|
) |
|
(origLight.excludeList != undefined and origLight.excludeList.count != 0): ( |
|
r.excludeIncludeMod = false |
|
r.excludeList = origLight.excludeList |
|
) |
|
default: () |
|
) |
|
|
|
— Intensitiy, Color, Texmap |
|
r.intensity = origLight.power |
|
r.intensityUnits = 1 — luminous (lm) |
|
|
|
|
|
r.colorMode = origLight.color_mode — 0: direct color, 1: kelvin temp |
|
r.color = origLight.color |
|
if r.colorMode == 1 do ( |
|
r.blackbodyTemp = origLight.color_temperature — kelvin |
|
) |
|
|
|
— Shape: 0: Sphere, 1: Rectangle, 2: Disk, 3: Cylinder |
|
case origLight.shape of ( |
|
0:( r.shape = 0 — point |
|
r.iesSharpnessFake = true |
|
r.width = 5 |
|
r.height = 5 |
|
) |
|
1:( r.shape = 1 — Rectangle |
|
r.width = if origLight.width != 0 then ( |
|
origLight.width |
|
) else ( |
|
5.0 |
|
) |
|
r.height = if origLight.length != 0 then ( |
|
origLight.length |
|
) else ( |
|
5.0 |
|
) |
|
) |
|
2:( r.shape = 2 — circle |
|
r.width = if origLight.diameter != 0 then ( |
|
origLight.diameter / 2.0 |
|
) else ( |
|
5.0 |
|
) |
|
) |
|
3:( r.shape = 0 — sphere |
|
r.width = if origLight.diameter != 0 then ( |
|
origLight.diameter / 2.0 |
|
) else ( |
|
5.0 |
|
) |
|
) |
|
4:( r.shape = 2 — vertical cylinder |
|
r.width = if origLight.diameter != 0 then ( |
|
origLight.diameter / 2.0 |
|
) else ( |
|
5.0 |
|
) |
|
) |
|
default:( |
|
r.shape = 0 — for everything else |
|
r.iesSharpnessFake = true |
|
r.width = 5 |
|
r.height = 5 |
|
) |
|
) |
|
|
|
— visibility |
|
r.visibleDirectly = false |
|
r.occludeOtherLights = origLight.castShadows |
|
|
|
— IES |
|
r.iesOn = true |
|
if origLight.ies_file != undefined do ( |
|
r.iesFile = origLight.ies_file |
|
) |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_VraySun origLight =( |
|
r = CoronaSun() |
|
|
|
— OnOff, Include/exclude |
|
r.on = origLight.enabled |
|
|
|
— Intensitiy, Color, Texmap |
|
r.intensity = origLight.intensity_multiplier |
|
|
|
if hasProperty origLight «color_mode« then ( |
|
if origLight.color_mode == 1 do ( — 0:filter 1:direct 2:override |
|
r.colorDirect = origLight.filter_Color |
|
r.colorMode = 0 |
|
) |
|
) |
|
— visibility |
|
r.visibleDirectly = not origLight.invisible |
|
|
|
r |
|
), |
|
|
|
fn convertFrom_mrSun origLight =( |
|
r = CoronaSun() |
|
r.on = origLight.on |
|
r.intensity = origLight.skymult |
|
|
|
r |
|
), |
|
|
|
— mr_Sky_Portal is only available in 3ds Max 2020 and older. After that, it was deprecated |
|
— and is only displayed in the scene as a «Light Stand-in». |
|
fn convertMrSkyPortalToCoronaLight inputLight =( |
|
assert((classof inputLight) == mr_Sky_Portal) |
|
|
|
local CUSTOM_COLOR_SOURCE = 1 |
|
if inputLight.mode == CUSTOM_COLOR_SOURCE then ( |
|
— In this mode the mr_Sky_Portal acts as a standard rectangular light. |
|
local outputLight = CoronaLight() |
|
|
|
outputLight.name = (if owner.converterSettings.addCoronaPrefix then ( |
|
owner.converterSettings.userPrefixStr |
|
) else ( |
|
«« |
|
)) + inputLight.name |
|
|
|
outputLight.on = inputLight.on |
|
outputLight.intensity = inputLight.multiplier |
|
|
|
local RGB_COLOR = 0 |
|
local TEXMAP = 2 |
|
outputLight.colorMode = if inputLight.map == undefined then ( RGB_COLOR ) else ( TEXMAP ) |
|
outputLight.color = inputLight.rgbFilter |
|
outputLight.texmap = inputLight.map |
|
|
|
local RECTANGLE = 1 |
|
outputLight.shape = RECTANGLE |
|
outputLight.width = inputLight.light_Width |
|
outputLight.height = inputLight.light_length |
|
outputLight.visibleDirectly = inputLight.Area_Visible |
|
|
|
/*return*/ outputLight |
|
) else ( |
|
— Corona Renderer does not support light portals anymore. |
|
/*return*/ #NoReplacement |
|
) |
|
) |
|
) |
|
|
|
lightConvMethods owner:this |
|
), |
|
|
|
— If inputMap is a textureMap, then this function attempts to convert it to CoronaBitmap. |
|
— Otherwise the inputMap is returned without any modifications. |
|
fn convertToCoronaBitmap inputMap =( |
|
if ((superclassof inputMap) != textureMap) then ( |
|
/*return*/ inputMap |
|
) else ( |
|
— If we have already converted this map, return the converted instance. |
|
local index = findItem converterTempData.originalMaps inputMap |
|
if index > 0 then ( |
|
/*return*/ converterTempData.newMaps[index] |
|
) else ( |
|
— Recursively convert also inputMap’s sub-maps, if any. |
|
for i = 1 to (getNumSubTexmaps inputMap) do ( |
|
local newTextureMap = convertToCoronaBitmap (getSubTexmap inputMap i) |
|
if newTextureMap != #NoReplacement then ( |
|
setSubTexmap inputMap i newTextureMap |
|
) |
|
) |
|
|
|
local outputMap = case (classof inputMap) of ( |
|
VrayColor: errorCatching mapConvMethods.convertFrom_VrayColor inputMap |
|
VrayDirt: errorCatching mapConvMethods.convertFrom_VrayDirt inputMap |
|
VrayNormalMap: errorCatching mapConvMethods.convertFrom_VrayNormalMap inputMap |
|
VraySky: errorCatching mapConvMethods.convertFrom_VraySky inputMap |
|
VRayCompTex: errorCatching mapConvMethods.convertFrom_VRayCompTex inputMap |
|
VRayEdgesTex: errorCatching mapConvMethods.convertFrom_VRayEdgesTex inputMap |
|
VRayGLSLTex: errorCatching mapConvMethods.convertFrom_VRayGLSLTex inputMap |
|
VRaySoftbox: errorCatching mapConvMethods.convertFrom_VRaySoftbox inputMap |
|
VRayHDRI: (if converterSettings.VrayHDRIToBitmaptexture then ( |
|
errorCatching mapConvMethods.convertFrom_VrayHDRI inputMap |
|
) else ( |
|
inputMap |
|
) |
|
) |
|
VRayTriplanarTex: errorCatching mapConvMethods.convertFrom_VRayTriplanarTex inputMap |
|
VRayColor2Bump: errorCatching mapConvMethods.convertFrom_VRayColor2Bump inputMap |
|
Bitmaptexture: (if converterSettings.bitmapTextureToCoronaBitmap then ( |
|
errorCatching mapConvMethods.convertFrom_BitmapTexture inputMap |
|
) else ( |
|
inputMap |
|
) |
|
) |
|
Normal_Bump: errorCatching mapConvMethods.convertFrom_Normal_Bump inputMap |
|
Autodesk_Map: errorCatching mapConvMethods.convertFrom_Autodesk_Map inputMap |
|
Ambient_Reflective_Occlusion__3dsmax: errorCatching mapConvMethods.convertFrom_Ambient_Reflective_Occlusion__3dsmax inputMap |
|
Multi_Sub_Map: errorCatching mapConvMethods.convertFrom_Multi_Sub_Map inputMap |
|
|
|
default: inputMap |
|
) |
|
|
|
— If the conversion was successful, add the map to the list of converted maps. |
|
if outputMap != inputMap then ( |
|
append converterTempData.originalMaps inputMap |
|
append converterTempData.newMaps outputMap |
|
) |
|
|
|
/*return*/ outputMap |
|
) |
|
) |
|
), |
|
|
|
— If the inputMaterial is a material, then this function attempts to convert it to CoronaLegacyMtl. |
|
— Otherwise the inputMaterial is returned without any modifications. |
|
fn convertToCoronaLegacyMtl inputMaterial =( |
|
if ((superclassof inputMaterial) != material) then ( |
|
/*return*/ inputMaterial |
|
) else ( |
|
local outputMaterial = case (classof inputMaterial) of ( |
|
StandardMaterial: errorCatching matConvMethods.convertFrom_Standard inputMaterial |
|
Arch___Design__mi: errorCatching matConvMethods.convertFrom_ArchAndDesign inputMaterial |
|
fR_Advanced: errorCatching matConvMethods.convertFrom_fR_Advanced inputMaterial |
|
fR_Architectural: errorCatching matConvMethods.convertFrom_fR_Architectural inputMaterial |
|
Autodesk_Material: errorCatching matConvMethods.convertFrom_AutodeskMtl inputMaterial |
|
Architectural: errorCatching matConvMethods.convertFrom_Architectural inputMaterial |
|
iray_Material: errorCatching matConvMethods.convertFrom_iray_Material inputMaterial |
|
|
|
default: inputMaterial |
|
) |
|
|
|
/*return*/ outputMaterial |
|
) |
|
), |
|
|
|
— zeroWeightsLerpBias represents a lerp bias used when both value1Weight and value2Weight are 0. |
|
fn valuesMix value1 value1Weight value2 value2Weight zeroWeightsLerpBias:0.5 =( |
|
assert (value1Weight >= 0.0) |
|
assert (value2Weight >= 0.0) |
|
assert ((0.0 <= zeroWeightsLerpBias) and (zeroWeightsLerpBias <= 1.0)) |
|
|
|
if (value1Weight + value2Weight) == 0.0 then ( |
|
/*return*/ lerp value1 value2 zeroWeightsLerpBias |
|
) else ( |
|
local weightSum = value1Weight + value2Weight |
|
— Do not use formula (value1 + value2) / weightSum. The reason for this is that color type in |
|
— 3ds Max can not have value larger than 255 and this could pose problems if value1 + value2 > 255. |
|
/*return*/ value1 * (value1Weight / weightSum) + value2 * (value2Weight / weightSum) |
|
) |
|
), |
|
|
|
— mixOperation:6 == Mix |
|
— To read more about mixOperation parameter consult CoronaMix’s MAXScript API documentation. |
|
— zeroWeightsLerpBias represents a lerp bias used when both value1Weight and value2Weight are 0. |
|
fn mapsMix mapBottom mapBottomWeight mapTop mapTopWeight mixNodeName mixOperation:6 zeroWeightsLerpBias:0.5 =( |
|
assert (mapBottomWeight >= 0.0) |
|
assert (mapTopWeight >= 0.0) |
|
assert ((0.0 <= zeroWeightsLerpBias) and (zeroWeightsLerpBias <= 1.0)) |
|
|
|
local cMix = CoronaMix mixOperation:mixOperation mixInSRgb:false |
|
cMix.name = mixNodeName |
|
|
|
cMix.texmapBottom = mapBottom |
|
cMix.texmapTop = mapTop |
|
|
|
— mixAmount == 1 prefers top map. |
|
— mixAmount == 0 prefers bottom map. |
|
local SUBTRACT = 1 |
|
local MULTIPLY = 2 |
|
local DIVIDE = 3 |
|
if mixOperation == SUBTRACT or mixOperation == MULTIPLY or mixOperation == DIVIDE then ( |
|
cMix.mixAmount = 1.0 — For subtraction, multiplication and division to work as expected, the mixAmount must be set to 1. |
|
) else ( |
|
if (mapBottomWeight + mapTopWeight) == 0.0 then ( |
|
cMix.mixAmount = zeroWeightsLerpBias |
|
) else ( |
|
cMix.mixAmount = mapTopWeight / (mapBottomWeight + mapTopWeight) |
|
) |
|
) |
|
|
|
/*return*/ cMix |
|
), |
|
|
|
— numberOrColor is expected to be either integer, float or color type (checked by an assert). |
|
fn createCoronaColorNode numberOrColor nodeName =( |
|
local coronaColorNode = CoronaColor() |
|
coronaColorNode.name = nodeName |
|
|
|
if (classof numberOrColor) == color then ( |
|
coronaColorNode.color = numberOrColor |
|
) else ( |
|
assert (((classof numberOrColor) == float) or ((classof numberOrColor) == integer)) |
|
|
|
if (classof numberOrColor) == integer then ( |
|
numberOrColor = numberOrColor as float |
|
) |
|
|
|
if numberOrColor > 1.0 then ( |
|
local FLOATING_POINT_MODE = 1 |
|
coronaColorNode.method = FLOATING_POINT_MODE |
|
coronaColorNode.colorHdr = Point3 numberOrColor numberOrColor numberOrColor |
|
) else ( |
|
local channelValue = numberOrColor * MAX_COLOR_VALUE |
|
coronaColorNode.color = color channelValue channelValue channelValue |
|
) |
|
) |
|
|
|
/*return*/ coronaColorNode |
|
), |
|
|
|
— numberOrColor is expected to be either integer, float or color type (checked by an assert). |
|
fn mapColorMix map mapWeight numberOrColor colorWeight colorNodeName mixNodeName =( |
|
local coronaColorNode = createCoronaColorNode numberOrColor colorNodeName |
|
|
|
/*return*/ mapsMix map mapWeight coronaColorNode colorWeight mixNodeName |
|
), |
|
|
|
— If the input string has only 1 character it is returned as is. |
|
fn capitalizeFirstLetter str =( |
|
if str.count >= 2 then ( — Prevent out of bounds access in case of short strings. |
|
local firstLetter = substring str 1 1 |
|
local remainingText = substring str 2 —1 |
|
/*return*/ (toUpper firstLetter) + remainingText |
|
) else ( |
|
/*return*/ str |
|
) |
|
), |
|
|
|
fn usesTranslucencyCoronaLegacyMtl inputMaterial =( |
|
assert ((classof inputMaterial) == CoronaLegacyMtl) |
|
/*return*/ usesLobeCoronaMtl inputMaterial.levelTranslucency inputMaterial.texmapTranslucencyFraction inputMaterial.texmapOnTranslucencyFraction inputMaterial.mapamountTranslucencyFraction inputMaterial.colorTranslucency |
|
), |
|
|
|
fn usesRefractionCoronaLegacyMtl inputMaterial =( |
|
assert ((classof inputMaterial) == CoronaLegacyMtl) |
|
/*return*/ usesLobeCoronaMtl inputMaterial.levelRefract inputMaterial.texmapRefract inputMaterial.texmapOnRefract inputMaterial.mapamountRefract inputMaterial.colorRefract |
|
), |
|
|
|
fn usesVolumetricScatteringCoronaLegacyMtl inputMaterial =( |
|
assert ((classof inputMaterial) == CoronaLegacyMtl) |
|
/*return*/ (inputMaterial.mediaMode == 1) and (inputMaterial.absorptionDistance > 0) |
|
), |
|
|
|
fn usesSssCoronaLegacyMtl inputMaterial =( |
|
assert ((classof inputMaterial) == CoronaLegacyMtl) |
|
/*return*/ (inputMaterial.mediaMode == 0) and (inputMaterial.levelSss > 0) |
|
), |
|
|
|
fn usesReflectionCoronaLegacyMtl inputMaterial =( |
|
assert ((classof inputMaterial) == CoronaLegacyMtl) |
|
/*return*/ usesLobeCoronaMtl inputMaterial.levelReflect inputMaterial.texmapReflect inputMaterial.texmapOnReflect inputMaterial.mapamountReflect inputMaterial.colorReflect |
|
), |
|
|
|
fn computeEffectiveMapWeight mapOn mapWeight =( |
|
if mapOn then ( |
|
/*return*/ mapWeight |
|
) else ( |
|
/*return*/ 0.0 |
|
) |
|
), |
|
|
|
fn fresnelIorMapIsActiveCoronaLegacyMtl inputMaterial =( |
|
assert ((classof inputMaterial) == CoronaLegacyMtl) |
|
/*return*/ mapIsActive inputMaterial.texmapFresnelIor inputMaterial.texmapOnFresnelIor inputMaterial.mapamountFresnelIor |
|
), |
|
|
|
— If some map is provided and its amount == max map amount, then the original map is returned. If its |
|
— amount != max map amount then a CoronaMix node, mixing the map and the corresponding parameter |
|
— according to mapOn and mapAmount parameters, is returned. Otherwise «undefined» is returned. |
|
fn tryGetMapColorMixOrMap paramName numberOrColor map mapOn mapAmount maxMapAmount =( |
|
local effectiveMapWeight = computeEffectiveMapWeight mapOn mapAmount |
|
|
|
if (map != undefined) and (effectiveMapWeight < maxMapAmount) then ( |
|
local colorContribution = maxMapAmount — effectiveMapWeight |
|
local mixNodeName = paramName + «Map_and_« + paramName |
|
/*return*/ mapColorMix map effectiveMapWeight numberOrColor colorContribution paramName mixNodeName |
|
) else ( |
|
/*return*/ map |
|
) |
|
), |
|
|
|
— Fuses parameters and maps of 2 material «layers» to a single material «layer» in a way so that it |
|
— creates minimal amount of new nodes and all the maps connected to the original material are |
|
— connected to the output material. Note that the original numeric / color parameter values may get |
|
— lost in the process because these values get mixed together to produce a single parameter value. |
|
— |
|
— Return value (bool) indicates whether CoronaMix node was used for mixing the input parameters. |
|
— mixOperation:6 == Mix |
|
— To read more about mixOperation parameter consult CoronaMix’s MAXScript API documentation. |
|
— zeroWeightsLerpBias represents a lerp bias used when both value1Weight and value2Weight are 0. |
|
— Unfortunately we can not pack outputMtlParam*(s) to struct, since structs in MAXScripts can not |
|
— contain references. |
|
fn zipParams &outputMtlParam &outputMtlParamMap &outputMtlParamMapOn &outputMtlParamMapAmount zipMtl1 zipMtl2 zipMtlParamMapMaxAmount mixOperation:6 zeroWeightsLerpBias:0.5 =( |
|
assert ((0.0 <= zeroWeightsLerpBias) and (zeroWeightsLerpBias <= 1.0)) |
|
|
|
outputMtlParam = valuesMix zipMtl1.param zipMtl1.paramLevel zipMtl2.param zipMtl2.paramLevel zeroWeightsLerpBias:zeroWeightsLerpBias |
|
|
|
if (zipMtl1.paramMap == undefined and zipMtl2.paramMap == undefined) then ( |
|
assert (outputMtlParamMap == undefined) |
|
|
|
if (approxEq zipMtl1.param zipMtl2.param) then ( |
|
assert (approxEq outputMtlParam zipMtl1.param) |
|
assert (approxEq outputMtlParam zipMtl2.param) |
|
|
|
) else ( |
|
— In this case we lose information about the original values of zipMtl1.param and |
|
— zipMtl2.param. While we could preserve these values by creating CoronaColor nodes and |
|
— CoronaMix node mixing them together, we don’t in favor of simpler resulting shading |
|
— networks. |
|
) |
|
return false |
|
) |
|
|
|
assert ((zipMtl1.paramMap != undefined) or (zipMtl2.paramMap != undefined)) |
|
|
|
if (zipMtl1.paramMap == undefined) and (approxEq zipMtl1.paramLevel 0.0) then ( |
|
assert (zipMtl2.paramMap != undefined) |
|
|
|
outputMtlParamMap = zipMtl2.paramMap |
|
outputMtlParamMapOn = zipMtl2.paramMapOn |
|
|
|
— In this case we lose information either about the original value of zipMtl1.param or |
|
— zipMtl2.param. While we could preserve these values by creating CoronaColor nodes and |
|
— CoronaMix node, we don’t in favor of simpler resulting shading networks. |
|
if (approxEq zipMtl2.paramLevel 0.0) then ( |
|
— outputMtlParam already handled. |
|
outputMtlParamMapAmount = valuesMix zipMtl1.paramMapAmount zipMtl1.paramLevel zipMtl2.paramMapAmount zipMtl2.paramLevel zeroWeightsLerpBias:zeroWeightsLerpBias |
|
) else ( |
|
assert (approxEq outputMtlParam zipMtl2.param) |
|
outputMtlParamMapAmount = zipMtl2.paramMapAmount |
|
) |
|
return false |
|
) |
|
|
|
if (zipMtl2.paramMap == undefined) and (approxEq zipMtl2.paramLevel 0.0) then ( |
|
assert (zipMtl1.paramMap != undefined) |
|
|
|
— In this case we lose information about the original value of zipMtl2.param. While we could |
|
— preserve this value by creating CoronaColor nodes and CoronaMix node, we don’t in favor of |
|
— simpler resulting shading networks. |
|
assert (approxEq outputMtlParam zipMtl1.param) |
|
outputMtlParamMap = zipMtl1.paramMap |
|
outputMtlParamMapOn = zipMtl1.paramMapOn |
|
outputMtlParamMapAmount = zipMtl1.paramMapAmount |
|
return false |
|
) |
|
|
|
— Set the output map to max amount and enable it, since in most of the following cases we will |
|
— account for these parameters in the corresponding shading networks. |
|
outputMtlParamMapOn = true |
|
outputMtlParamMapAmount = zipMtlParamMapMaxAmount |
|
|
|
local usesMixNode = false |
|
|
|
zipMtl1.paramName = capitalizeFirstLetter zipMtl1.paramName |
|
zipMtl2.paramName = capitalizeFirstLetter zipMtl2.paramName |
|
|
|
if (zipMtl1.paramMap == zipMtl2.paramMap) then ( |
|
assert (zipMtl1.paramMap != undefined) |
|
assert (zipMtl2.paramMap != undefined) |
|
|
|
local effectiveZipMtl1MapAmount = computeEffectiveMapWeight zipMtl1.paramMapOn zipMtl1.paramMapAmount |
|
local effectiveZipMtl2MapAmount = computeEffectiveMapWeight zipMtl2.paramMapOn zipMtl2.paramMapAmount |
|
|
|
if (approxEq effectiveZipMtl1MapAmount zipMtlParamMapMaxAmount) and (approxEq effectiveZipMtl2MapAmount zipMtlParamMapMaxAmount) then ( |
|
assert (approxEq effectiveZipMtl1MapAmount effectiveZipMtl2MapAmount) |
|
|
|
— No need to take zipMtl1.param and zipMtl2.param into account, since in this case they have |
|
— no contribution. |
|
|
|
outputMtlParamMap = zipMtl1.paramMap |
|
assert (outputMtlParamMap == zipMtl2.paramMap) |
|
|
|
) else if (approxEq zipMtl1.param zipMtl2.param) then ( |
|
assert (approxEq outputMtlParam zipMtl1.param) |
|
assert (approxEq outputMtlParam zipMtl2.param) |
|
assert ((effectiveZipMtl1MapAmount != zipMtlParamMapMaxAmount) and (effectiveZipMtl2MapAmount != zipMtlParamMapMaxAmount)) — This case should be already handled. |
|
|
|
outputMtlParamMap = zipMtl1.paramMap |
|
assert (outputMtlParamMap == zipMtl2.paramMap) |
|
|
|
outputMtlParamMapOn = zipMtl1.paramMapOn or zipMtl2.paramMapOn |
|
|
|
if (approxEq effectiveZipMtl1MapAmount effectiveZipMtl2MapAmount) then ( |
|
outputMtlParamMapAmount = effectiveZipMtl1MapAmount |
|
assert (outputMtlParamMapAmount == effectiveZipMtl2MapAmount) |
|
|
|
) else ( |
|
assert (effectiveZipMtl1MapAmount != effectiveZipMtl2MapAmount) |
|
outputMtlParamMapAmount = valuesMix effectiveZipMtl1MapAmount zipMtl1.paramLevel effectiveZipMtl2MapAmount zipMtl2.paramLevel zeroWeightsLerpBias:zeroWeightsLerpBias |
|
) |
|
) else ( |
|
assert (zipMtl1.param != zipMtl2.param) |
|
assert ((effectiveZipMtl1MapAmount != zipMtlParamMapMaxAmount) or (effectiveZipMtl2MapAmount != zipMtlParamMapMaxAmount)) — This case should be already handled. |
|
|
|
local zipMtl1MapColorMixOrMap = tryGetMapColorMixOrMap zipMtl1.paramName zipMtl1.param zipMtl1.paramMap zipMtl1.paramMapOn zipMtl1.paramMapAmount zipMtlParamMapMaxAmount |
|
assert (zipMtl1MapColorMixOrMap != undefined) |
|
|
|
local zipMtl2MapColorMixOrMap = tryGetMapColorMixOrMap zipMtl2.paramName zipMtl2.param zipMtl2.paramMap zipMtl2.paramMapOn zipMtl2.paramMapAmount zipMtlParamMapMaxAmount |
|
assert (zipMtl2MapColorMixOrMap != undefined) |
|
|
|
assert (((classof zipMtl1MapColorMixOrMap) == CoronaMix) or ((classof zipMtl2MapColorMixOrMap) == CoronaMix)) — Since at least one of the effectiveZipMtl1MapAmount and effectiveZipMtl2MapAmount values is < zipMtlParamMapMaxAmount and both zipMtl1.paramMap and zipMtl2.paramMap are not undefined, there should be at least one CoronaMix. |
|
|
|
local mixNodeName = zipMtl1.paramName + «_and_« + zipMtl2.paramName |
|
outputMtlParamMap = mapsMix zipMtl1MapColorMixOrMap zipMtl1.paramLevel zipMtl2MapColorMixOrMap zipMtl2.paramLevel mixNodeName mixOperation:mixOperation zeroWeightsLerpBias:zeroWeightsLerpBias |
|
usesMixNode = true |
|
) |
|
) else ( |
|
local zipMtl1ParamMapColorMixOrMap = tryGetMapColorMixOrMap zipMtl1.paramName zipMtl1.param zipMtl1.paramMap zipMtl1.paramMapOn zipMtl1.paramMapAmount zipMtlParamMapMaxAmount |
|
if zipMtl1ParamMapColorMixOrMap == undefined then ( |
|
assert (zipMtl1.paramLevel > 0.0) |
|
|
|
zipMtl1ParamMapColorMixOrMap = createCoronaColorNode zipMtl1.param zipMtl1.paramName |
|
) |
|
|
|
local zipMtl2ParamMapColorMixOrMap = tryGetMapColorMixOrMap zipMtl2.paramName zipMtl2.param zipMtl2.paramMap zipMtl2.paramMapOn zipMtl2.paramMapAmount zipMtlParamMapMaxAmount |
|
if zipMtl2ParamMapColorMixOrMap == undefined then ( |
|
assert (zipMtl2.paramLevel > 0.0) |
|
|
|
zipMtl2ParamMapColorMixOrMap = createCoronaColorNode zipMtl2.param zipMtl2.paramName |
|
) |
|
|
|
local mixNodeName = zipMtl1.paramName + «_and_« + zipMtl2.paramName |
|
outputMtlParamMap = mapsMix zipMtl1ParamMapColorMixOrMap zipMtl1.paramLevel zipMtl2ParamMapColorMixOrMap zipMtl2.paramLevel mixNodeName mixOperation:mixOperation zeroWeightsLerpBias:zeroWeightsLerpBias |
|
usesMixNode = true |
|
) |
|
|
|
if (zipMtl1.paramMap != undefined) or (zipMtl2.paramMap != undefined) then ( |
|
assert (outputMtlParamMap != undefined) |
|
) else ( |
|
assert (outputMtlParamMap == undefined) |
|
assert (usesMixNode == false) |
|
) |
|
|
|
/*return*/ usesMixNode |
|
), |
|
|
|
— The inputMaterial is expected to be CoronaLegacyMtl (checked by an assert). |
|
fn convertCoronaLegacyMtlToCoronaPhysicalMtl inputMaterial translucencyEnablesThinShell &problematicMtls =( |
|
assert ((classof inputMaterial) == CoronaLegacyMtl) |
|
|
|
local outputMaterial = CoronaPhysicalMtl() |
|
outputMaterial.name = inputMaterial.name |
|
|
|
— Switch to «Glossiness» mode, since CoronaLegacyMtl uses Glossiness workflow. If we set |
|
— roughness values first and then switchned the roughnessMode, the material would automatically |
|
— recalculate (change) the roughness values. |
|
outputMaterial.roughnessMode = 1 |
|
|
|
— Need to explicitly set this because the default is user-configurable and all the following |
|
— computations rely on the assumption that this material uses IoR parameters. |
|
outputMaterial.iorMode = 0 |
|
|
|
local metal = false |
|
if not inputMaterial.thin and not (usesTranslucencyCoronaLegacyMtl inputMaterial) and not (usesRefractionCoronaLegacyMtl inputMaterial) and not (usesVolumetricScatteringCoronaLegacyMtl inputMaterial) and not (usesSssCoronaLegacyMtl inputMaterial) and not (fresnelIorMapIsActiveCoronaLegacyMtl inputMaterial) and (inputMaterial.fresnelIor > 3.0) then ( |
|
metal = true |
|
) |
|
|
|
— Basic options |
|
|
|
outputMaterial.metalnessMode = if metal then ( 1 ) else ( 0 ) |
|
outputMaterial.useThinMode = inputMaterial.thin |
|
|
|
if translucencyEnablesThinShell and (usesTranslucencyCoronaLegacyMtl inputMaterial) then ( |
|
outputMaterial.useThinMode = true |
|
) |
|
|
|
— Don’t know how it is possible, but in some scenes the levelReflect was negative. |
|
local sanitizedLevelReflect = amax #(0.0, inputMaterial.levelReflect) |
|
|
|
— Set baseLevel, basecolor, baseTexmap, baseTexmapOn, baseMapAmount. |
|
— We do not set baseLevel yet, because baseColor (or baseTexmap) might end up being a result of |
|
— mix between input colorDiffuse and input colorReflect (or their corresponding textures) and in |
|
— such case we only want to multiply the colorDiffuse part by the baseLevel (i.e. we do not want |
|
— to affect colorReflect by baseLevel). |
|
outputMaterial.baseLevel = 1.0 |
|
— Non-metals do not tint reflections, so in such case we don’t take reflection color into |
|
— account. |
|
local levelReflect = if metal then ( sanitizedLevelReflect ) else ( 0.0 ) |
|
— We do not multiply input colorDiffuse by input levelDiffuse yet, because colorDiffuse might end |
|
— up being mixed with inputMaterial.texmapDiffuse and in such case we only want to multiply the |
|
— resulting mix by levelDiffuse. If we multiplied also colorDiffuse, the corresponding |
|
— multiplication by levelDiffuse would be applied twice. |
|
local zipMtl1 = ZipMtl inputMaterial.colorDiffuse «colorDiffuse« inputMaterial.levelDiffuse inputMaterial.texmapDiffuse inputMaterial.texmapOnDiffuse inputMaterial.mapamountDiffuse |
|
— If non-metal we use the texmapReflect for reducing effect of IoR. |
|
local texmapReflect = if metal then ( inputMaterial.texmapReflect ) else ( undefined ) |
|
local zipMtl2 = ZipMtl inputMaterial.colorReflect «colorReflect« levelReflect texmapReflect inputMaterial.texmapOnReflect inputMaterial.mapamountReflect |
|
local MAP_MAX_AMOUNT = 100.0 |
|
local zeroWeightsLerpBias = if metal then ( 0.5 ) else ( 0.0 ) |
|
local baseTexmapUsesMixNode = zipParams &outputMaterial.basecolor &outputMaterial.baseTexmap &outputMaterial.baseTexmapOn &outputMaterial.baseMapAmount zipMtl1 zipMtl2 MAP_MAX_AMOUNT zeroWeightsLerpBias:zeroWeightsLerpBias |
|
if baseTexmapUsesMixNode then ( |
|
assert ((classof outputMaterial.baseTexmap) == CoronaMix) |
|
|
|
— In the top slot there is either input colorReflect, input texmapReflect or mix of the two. |
|
— In the bottom slot there is either input colorDiffuse, input texmapDiffuse or mix of the |
|
— two. Since we do not want to affect the input reflection color parameters by levelDiffuse, |
|
— let’s multiply only the bottom slot by levelDiffuse. |
|
outputMaterial.baseTexmap.scaleBottom = inputMaterial.levelDiffuse |
|
|
|
) else if (outputMaterial.baseTexmap != undefined) and (outputMaterial.baseTexmap == inputMaterial.texmapDiffuse) then ( |
|
— In this case the input reflection color parameters are ignored, so we may set the baseLevel |
|
— value to the value of input levelDiffuse. |
|
outputMaterial.baseLevel = inputMaterial.levelDiffuse |
|
) |
|
— Take into account also value of input levelDiffuse when computing baseColor (which was |
|
— previously ignored). |
|
outputMaterial.basecolor = valuesMix (inputMaterial.colorDiffuse * inputMaterial.levelDiffuse) inputMaterial.levelDiffuse inputMaterial.colorReflect levelReflect zeroWeightsLerpBias:zeroWeightsLerpBias |
|
|
|
— Set baseRoughness, baseRoughnessTexmap, baseRoughnessTexmapOn, baseRoughnessMapAmount. |
|
— Metals do not refract light, so in such case we don’t take refraction roughness into account. |
|
local levelRefract = if metal then ( 0.0 ) else ( inputMaterial.levelRefract ) |
|
local zipMtl1 = ZipMtl inputMaterial.reflectGlossiness «reflectGlossiness« sanitizedLevelReflect inputMaterial.texmapReflectGlossiness inputMaterial.texmapOnReflectGlossiness inputMaterial.mapamountReflectGlossiness |
|
local zipMtl2 = ZipMtl inputMaterial.refractGlossiness «refractGlossiness« levelRefract inputMaterial.texmapRefractGlossiness inputMaterial.texmapOnRefractGlossiness inputMaterial.mapamountRefractGlossiness |
|
zipParams &outputMaterial.baseRoughness &outputMaterial.baseRoughnessTexmap &outputMaterial.baseRoughnessTexmapOn &outputMaterial.baseRoughnessMapAmount zipMtl1 zipMtl2 MAP_MAX_AMOUNT zeroWeightsLerpBias:0.0 |
|
|
|
— Set baseIor, baseIorTexmap, baseIorTexmapOn, baseIorMapAmount. |
|
local zipMtl1 = ZipMtl inputMaterial.fresnelIor «fresnelIor« sanitizedLevelReflect inputMaterial.texmapFresnelIor inputMaterial.texmapOnFresnelIor inputMaterial.mapamountFresnelIor |
|
local zipMtl2 = ZipMtl inputMaterial.Ior «Ior« levelRefract inputMaterial.texmapIor inputMaterial.texmapOnIor inputMaterial.mapamountIor |
|
zipParams &outputMaterial.baseIor &outputMaterial.baseIorTexmap &outputMaterial.baseIorTexmapOn &outputMaterial.baseIorMapAmount zipMtl1 zipMtl2 MAP_MAX_AMOUNT zeroWeightsLerpBias:0.0 |
|
|
|
— Since CoronaPhysicalMtl does not have a reflection level parameter nor can not use reflection |
|
— level map, the only way to reproduce look of the inputMaterial is by adjusting |
|
— CoronaPhysicalMtl’s IoR by input reflection level (or its IoR map by input reflection level |
|
— map respectively). |
|
local iorUnaffectedByLevelReflect = outputMaterial.baseIor |
|
|
|
local effectiveReflectLevel = ((colorToAverageLuminance inputMaterial.colorReflect) / MAX_COLOR_VALUE) * sanitizedLevelReflect |
|
assert((0.0 <= effectiveReflectLevel) and (effectiveReflectLevel <= 1.0)) |
|
|
|
outputMaterial.baseIor = lerp 1.0 outputMaterial.baseIor effectiveReflectLevel |
|
|
|
— If metal we use the texmapReflect as a tint for baseColor. |
|
local texmapReflect = if metal then ( undefined ) else ( inputMaterial.texmapReflect ) |
|
|
|
if (texmapReflect == undefined) and (outputMaterial.baseIorTexmap == undefined) then ( |
|
— Only need to set outputMaterial.baseIor which is already handled. |
|
|
|
) else ( |
|
— Set the output map to max amount and enable it, since in the following cases we will |
|
— account for these parameters in the corresponding shading networks. |
|
outputMaterial.baseIorTexmapOn = true |
|
outputMaterial.baseIorMapAmount = MAP_MAX_AMOUNT |
|
|
|
local MIX_NODE_NAME = «Adjusted_IoR« |
|
|
|
— Note that in the following 3 cases we must use iorUnaffectedByLevelReflect, since we |
|
— further multiply shading networks where this value is used by effectiveReflectLevel. Since |
|
— baseIor already accounts for effectiveReflectLevel if we used it here again, we would |
|
— effectively perform two multiplications by effectiveReflectLevel. |
|
if (texmapReflect == undefined) and (outputMaterial.baseIorTexmap != undefined) and (effectiveReflectLevel < 1.0) then ( |
|
— Adjust CoronaPhysicalMtl’s IoR map values using lerp(1, IoR map, luminance(reflection color) * reflection amount). |
|
|
|
local baseIorMapColorMixOrMap = tryGetMapColorMixOrMap «BaseIor« iorUnaffectedByLevelReflect outputMaterial.baseIorTexmap outputMaterial.baseIorTexmapOn outputMaterial.baseIorMapAmount MAP_MAX_AMOUNT |
|
assert (baseIorMapColorMixOrMap != undefined) |
|
|
|
local effectiveReflectLevelComplement = 1.0 — effectiveReflectLevel |
|
outputMaterial.baseIorTexmap = mapsMix (createCoronaColorNode white «One«) effectiveReflectLevelComplement baseIorMapColorMixOrMap effectiveReflectLevel MIX_NODE_NAME |
|
|
|
) else if (texmapReflect != undefined) and (outputMaterial.baseIorTexmap == undefined) then ( |
|
— Adjust CoronaPhysicalMtl’s IoR value using lerp(1, IoR value, reflection map * reflection amount). |
|
|
|
outputMaterial.baseIorTexmap = mapsMix (createCoronaColorNode white «One«) 1.0 (createCoronaColorNode iorUnaffectedByLevelReflect «IoR«) 1.0 MIX_NODE_NAME |
|
|
|
local reflectMapColorMixOrMap = tryGetMapColorMixOrMap «ColorReflect« inputMaterial.colorReflect texmapReflect inputMaterial.texmapOnReflect inputMaterial.mapamountReflect MAP_MAX_AMOUNT |
|
assert (reflectMapColorMixOrMap != undefined) |
|
|
|
outputMaterial.baseIorTexmap.texmapMix = if sanitizedLevelReflect < 1.0 then ( |
|
addCoronaColorCorrectNode «LevelReflect_Adjustment« reflectMapColorMixOrMap factor:sanitizedLevelReflect |
|
) else ( |
|
reflectMapColorMixOrMap |
|
) |
|
|
|
) else if (texmapReflect != undefined) and (outputMaterial.baseIorTexmap != undefined) then ( |
|
— Adjust CoronaPhysicalMtl’s IoR map values using lerp(1, IoR map, reflection map * reflection amount). |
|
|
|
local baseIorMapColorMixOrMap = tryGetMapColorMixOrMap «BaseIor« iorUnaffectedByLevelReflect outputMaterial.baseIorTexmap outputMaterial.baseIorTexmapOn outputMaterial.baseIorMapAmount MAP_MAX_AMOUNT |
|
assert (baseIorMapColorMixOrMap != undefined) |
|
|
|
outputMaterial.baseIorTexmap = mapsMix (createCoronaColorNode white «One«) 1.0 baseIorMapColorMixOrMap 1.0 MIX_NODE_NAME |
|
|
|
local reflectMapColorMixOrMap = tryGetMapColorMixOrMap «ColorReflect« inputMaterial.colorReflect texmapReflect inputMaterial.texmapOnReflect inputMaterial.mapamountReflect MAP_MAX_AMOUNT |
|
assert (reflectMapColorMixOrMap != undefined) |
|
|
|
outputMaterial.baseIorTexmap.texmapMix = if sanitizedLevelReflect < 1.0 then ( |
|
addCoronaColorCorrectNode «LevelReflect_Adjustment« reflectMapColorMixOrMap factor:sanitizedLevelReflect |
|
) else ( |
|
reflectMapColorMixOrMap |
|
) |
|
) |
|
) |
|
|
|
— The following step is necessary to prevent potential crashes. See this function’s documentation |
|
— for more detail. Note that we pass to the function the originally computed IoR value, before it |
|
— was adjusted by input reflection level. |
|
setFixedIorValueForFalloffMaps outputMaterial.baseIorTexmap iorUnaffectedByLevelReflect |
|
|
|
— Bump |
|
outputMaterial.baseBumpMapAmount = inputMaterial.mapamountBump |
|
outputMaterial.baseBumpTexmap = inputMaterial.texmapBump |
|
|
|
— Edge color |
|
if metal then ( |
|
outputMaterial.edgeColor = white |
|
) |
|
|
|
— Anisotropy |
|
outputMaterial.baseAnisotropy = inputMaterial.anisotropy |
|
outputMaterial.baseAnisotropyTexmap = inputMaterial.texmapReflectAnisotropy |
|
outputMaterial.baseAnisoRotation = inputMaterial.anisotropyRotation |
|
outputMaterial.baseAnisoRotationTexmap = inputMaterial.texmapReflectAnisotropyRotation |
|
|
|
— Translucency |
|
outputMaterial.translucencyFraction = inputMaterial.levelTranslucency |
|
outputMaterial.translucencyFractionTexmap = inputMaterial.texmapTranslucencyFraction |
|
outputMaterial.translucencyColor = inputMaterial.colorTranslucency |
|
outputMaterial.translucencyColorTexmap = inputMaterial.texmapTranslucency |
|
|
|
— Refraction |
|
outputMaterial.refractionAmount = inputMaterial.levelRefract |
|
— outputMaterial.refractionAmountTexmap = CoronaLegacyMtl does not support using a map for specifying refraction amount. |
|
outputMaterial.thinAbsorptionColor = inputMaterial.colorRefract |
|
— outputMaterial.thinAbsorptionTexmap = Will be set together with volumetric scattering texture. |
|
outputMaterial.useCaustics = inputMaterial.caustics |
|
outputMaterial.dispersionEnable = inputMaterial.refractDispersionEnable |
|
outputMaterial.dispersion = inputMaterial.refractDispersion |
|
|
|
— Opacity |
|
outputMaterial.opacityLevel = inputMaterial.levelOpacity |
|
outputMaterial.opacityCutout = inputMaterial.opacityCutout |
|
outputMaterial.opacityColor = inputMaterial.colorOpacity |
|
outputMaterial.opacityTexmap = inputMaterial.texmapOpacity |
|
|
|
— Displacement |
|
outputMaterial.displacementMinimum = inputMaterial.displacementMinimum |
|
outputMaterial.displacementMaximum = inputMaterial.displacementMaximum |
|
outputMaterial.displacementTexmap = inputMaterial.texmapDisplace |
|
outputMaterial.displacementWaterLevelOn = inputMaterial.displacementWaterLevelOn |
|
outputMaterial.displacementWaterLevel = inputMaterial.displacementWaterLevel |
|
|
|
— Clearcoat layer |
|
— CoronaLegacyMtl does not have a clearcoat lobe. |
|
|
|
— Sheen layer |
|
— CoronaLegacyMtl does not have a sheen lobe. |
|
|
|
— Media options |
|
|
|
— Volumetric scattering |
|
— Set volumetricAbsorptionColor, volumetricAbsorptionTexmap, volumetricAbsorptionTexmapOn, volumetricAbsorptionMapAmount. |
|
— Color of refraction / volumetric absorption in CoronaLegacyMtl is computed as colorRefract * volumetricAbsorptionColor. |
|
local zipMtl1 = ZipMtl inputMaterial.colorRefract «colorRefract« 1.0 inputMaterial.texmapRefract inputMaterial.texmapOnRefract inputMaterial.mapamountRefract |
|
local zipMtl2 = ZipMtl inputMaterial.absorptionColor «absorptionColor« 1.0 inputMaterial.texmapAbsorption inputMaterial.texmapOnAbsorption inputMaterial.mapamountAbsorption |
|
local MIX_OPERATION_MULTIPLY = 2 |
|
local volumetricAbsorptionTexmapUsesMixNode = zipParams &outputMaterial.volumetricAbsorptionColor &outputMaterial.volumetricAbsorptionTexmap &outputMaterial.volumetricAbsorptionTexmapOn &outputMaterial.volumetricAbsorptionMapAmount zipMtl1 zipMtl2 MAP_MAX_AMOUNT mixOperation:MIX_OPERATION_MULTIPLY |
|
|
|
if volumetricAbsorptionTexmapUsesMixNode then ( |
|
assert ((classof outputMaterial.volumetricAbsorptionTexmap) == CoronaMix) |
|
|
|
— CoronaLegacyMtl does not have a thin absorption parameter, however its refraction color parameter causes the same effect. |
|
outputMaterial.thinAbsorptionTexmap = outputMaterial.volumetricAbsorptionTexmap.texmapBottom — Which is inputMaterial.colorRefract. |
|
) |
|
— Visible refraction color in CoronaLegacyMtl is a result of multiplication of its volumetric absorption color and refraction color. |
|
outputMaterial.volumetricAbsorptionColor = inputMaterial.colorRefract * inputMaterial.absorptionColor |
|
|
|
outputMaterial.volumetricScatteringColor = inputMaterial.scatterColor |
|
outputMaterial.volumetricScatteringTexmap = inputMaterial.texmapScatterColor |
|
outputMaterial.attenuationDistance = inputMaterial.absorptionDistance |
|
outputMaterial.scatterDirectionality = inputMaterial.scatterDirectionality |
|
outputMaterial.scatterSingleBounce = inputMaterial.singleBounceOnly |
|
|
|
— Subsurface scattering |
|
outputMaterial.sssAmount = inputMaterial.levelSss |
|
outputMaterial.sssAmountTexmap = inputMaterial.texmapSssAmount |
|
outputMaterial.sssRadius = inputMaterial.sssRadius |
|
outputMaterial.sssRadiusTexmap = inputMaterial.texmapSssRadius |
|
outputMaterial.sssScatterColor = inputMaterial.sssScatterColor |
|
outputMaterial.sssScatterTexmap = inputMaterial.texmapSssScatterColor |
|
|
|
— Advanced options |
|
|
|
— Self-illumination |
|
outputMaterial.selfIllumLevel = inputMaterial.levelSelfIllum |
|
outputMaterial.selfIllumColor = inputMaterial.colorSelfIllum |
|
outputMaterial.selfIllumTexmap = inputMaterial.texmapSelfIllum |
|
|
|
— Anisotropy orientation |
|
outputMaterial.anisotropyOrientationMode = inputMaterial.anisotropyOrientationMode |
|
outputMaterial.anisotropyOrientationUvwChannel = inputMaterial.anisotropyOrientationUvwChannel |
|
|
|
outputMaterial.gBufferOverride = inputMaterial.gBufferOverride |
|
outputMaterial.alphaMode = inputMaterial.alphaMode |
|
outputMaterial.renderElementPropagation = inputMaterial.renderElementPropagation |
|
|
|
outputMaterial.bgOverrideReflectTexmap = inputMaterial.texmapReflectBgOverride |
|
outputMaterial.bgOverrideRefractTexmap = inputMaterial.texmapRefractBgOverride |
|
|
|
— Maps options |
|
— outputMaterial.baseTexmapOn already handled. |
|
— outputMaterial.baseMapAmount already handled. |
|
— outputMaterial.baseRoughnessTexmapOn already handled. |
|
— outputMaterial.baseRoughnessMapAmount already handled. |
|
outputMaterial.baseAnisotropyTexmapOn = inputMaterial.texmapOnAnisotropy |
|
outputMaterial.baseAnisotropyMapAmount = inputMaterial.mapamountAnisotropy |
|
outputMaterial.baseAnisoRotationTexmapOn = inputMaterial.texmapOnAnisotropyRotation |
|
outputMaterial.baseAnisoRotationMapAmount = inputMaterial.mapamountAnisotropyRotation |
|
— outputMaterial.baseIorTexmapOn already handled. |
|
— outputMaterial.baseIorMapAmount already handled. |
|
— outputMaterial.edgeColorTexmapOn = CoronaLegacyMtl does not have such parameter. |
|
— outputMaterial.edgeColorMapAmount = CoronaLegacyMtl does not have such parameter. |
|
outputMaterial.translucencyFractionTexmapOn = inputMaterial.texmapOnTranslucencyFraction |
|
outputMaterial.translucencyFractionMapAmount = inputMaterial.mapamountTranslucencyFraction |
|
outputMaterial.translucencyColorTexmapOn = inputMaterial.texmapOnTranslucency |
|
outputMaterial.translucencyColorMapAmount = inputMaterial.mapamountTranslucency |
|
— outputMaterial.metalnessTexmapOn = CoronaLegacyMtl does not have such parameter. |
|
outputMaterial.refractionAmountTexmapOn = inputMaterial.texmapOnRefract |
|
outputMaterial.refractionAmountMapAmount = inputMaterial.mapamountRefract |
|
outputMaterial.thinAbsorptionTexmapOn = inputMaterial.texmapOnRefract |
|
outputMaterial.thinAbsorptionMapAmount = inputMaterial.mapamountRefract |
|
outputMaterial.opacityTexmapOn = inputMaterial.texmapOnOpacity |
|
outputMaterial.opacityMapAmount = inputMaterial.mapamountOpacity |
|
outputMaterial.selfIllumTexmapOn = inputMaterial.texmapOnSelfIllum |
|
outputMaterial.selfillumMapAmount = inputMaterial.mapamountSelfIllum |
|
outputMaterial.baseBumpTexmapOn = inputMaterial.texmapOnBump |
|
outputMaterial.displacementTexmapOn = inputMaterial.texmapOnDisplacement |
|
— CoronaLegacyMtl does not have a clearcoat lobe. |
|
— CoronaLegacyMtl does not have a sheen lobe. |
|
outputMaterial.sssAmountTexmapOn = inputMaterial.texmapOnSssAmount |
|
outputMaterial.sssAmountMapAmount = inputMaterial.mapamountSssAmount |
|
outputMaterial.sssRadiusTexmapOn = inputMaterial.texmapOnSssRadius |
|
outputMaterial.sssRadiusMapAmount = inputMaterial.mapamountSssRadius |
|
outputMaterial.sssScatterTexmapOn = inputMaterial.texmapOnSssScatterColor |
|
outputMaterial.sssScatterMapAmount = inputMaterial.mapamountSssScatterColor |
|
outputMaterial.volumetricAbsorptionTexmapOn = inputMaterial.texmapOnAbsorption |
|
outputMaterial.volumetricAbsorptionMapAmount = inputMaterial.mapamountAbsorption |
|
outputMaterial.volumetricScatteringTexmapOn = inputMaterial.texmapOnScatterColor |
|
outputMaterial.volumetricScatteringMapAmount = inputMaterial.mapamountScatterColor |
|
outputMaterial.bgOverrideReflectTexmapOn = inputMaterial.texmapOnReflectBgOverride |
|
outputMaterial.bgOverrideRefractTexmapOn = inputMaterial.texmapOnRefractBgOverride |
|
|
|
if usesRefractionCoronaLegacyMtl inputMaterial then ( |
|
append problematicMtls.usedRefractionColor outputMaterial.name |
|
) |
|
|
|
/*return*/ outputMaterial |
|
), |
|
|
|
fn usesRefractionVRayMtl inputMaterial =( |
|
assert ((classof inputMaterial) == VRayMtl) |
|
|
|
if mapIsActive inputMaterial.texmap_refraction inputMaterial.texmap_refraction_on inputMaterial.texmap_refraction_multiplier then ( |
|
/*return*/ true |
|
) else ( |
|
/*return*/ inputMaterial.Refraction != black |
|
) |
|
), |
|
|
|
fn usesReflectionVRayMtl inputMaterial =( |
|
assert ((classof inputMaterial) == VRayMtl) |
|
|
|
if mapIsActive inputMaterial.texmap_reflection inputMaterial.texmap_reflection_on inputMaterial.texmap_reflection_multiplier then ( |
|
/*return*/ true |
|
) else ( |
|
/*return*/ inputMaterial.Reflection != black |
|
) |
|
), |
|
|
|
fn usesSssVRayMtl inputMaterial =( |
|
assert ((classof inputMaterial) == VRayMtl) |
|
|
|
/*return*/ inputMaterial.translucency_on > 0 |
|
), |
|
|
|
fn reflectionFresnelMapIsActiveVRayMtl inputMaterial =( |
|
assert ((classof inputMaterial) == VRayMtl) |
|
|
|
if inputMaterial.reflection_lockIOR then ( |
|
/*return*/ mapIsActive inputMaterial.texmap_refractionIOR inputMaterial.texmap_refractionIOR_on inputMaterial.texmap_refractionIOR_multiplier |
|
) else ( |
|
/*return*/ mapIsActive inputMaterial.texmap_reflectionIOR inputMaterial.texmap_reflectionIOR_on inputMaterial.texmap_reflectionIOR_multiplier |
|
) |
|
), |
|
|
|
fn metalnessMapIsActiveVRayMtl inputMaterial =( |
|
assert ((classof inputMaterial) == VRayMtl) |
|
assert (hasProperty inputMaterial «texmap_metalness«) |
|
|
|
/*return*/ mapIsActive inputMaterial.texmap_metalness inputMaterial.texmap_metalness_on inputMaterial.texmap_metalness_multiplier |
|
), |
|
|
|
fn isMetalVRayMtl inputMaterial =( |
|
assert ((classof inputMaterial) == VRayMtl) |
|
|
|
— Property «refraction_thinWalled» is only available in VRayMtl since V-Ray 5. |
|
local isThinWalled = if hasProperty inputMaterial «refraction_thinWalled« then ( inputMaterial.refraction_thinWalled ) else ( false ) |
|
local usesRefraction = usesRefractionVRayMtl inputMaterial |
|
local usesSss = usesSssVRayMtl inputMaterial |
|
local reflectionFresnelMapIsActive = reflectionFresnelMapIsActiveVRayMtl inputMaterial |
|
local reflectionFresnelEffectEnabled = inputMaterial.reflection_fresnel |
|
local effectiveReflectionIor = if inputMaterial.reflection_lockIOR then ( inputMaterial.refraction_ior ) else ( inputMaterial.reflection_IOR ) |
|
|
|
— Metalness parameters are only available in VRayMtl since V-Ray 4. |
|
local metalnessMapIsActive = if hasProperty inputMaterial «texmap_metalness« then ( |
|
metalnessMapIsActiveVRayMtl inputMaterial |
|
) else ( |
|
false |
|
) |
|
|
|
local reflectionMetalnessIsPositive = if hasProperty inputMaterial «reflection_metalness« then ( |
|
inputMaterial.reflection_metalness > 0.0 |
|
) else ( |
|
false |
|
) |
|
|
|
— Metals are not expected to be thin-walled, to exhibit refraction and subsurface scattering. |
|
— If the materials uses a texture map to define its Fresnel values, we can not determine the |
|
— values used and therefore can not determine whether the material is a metal or not. |
|
— If the material does not use Fresnel effect, it is very (however unrealistically) reflective |
|
— so in such case we assume that the material should represent a metal. |
|
— Materials with IoR > 3 do not exist in real world but users of graphics software sometimes use |
|
— such values as a hack to define very reflective materials — so in such case we also assume that |
|
— the material should represent a metal. |
|
/*return*/ (not isThinWalled) and (not usesRefraction) and (not usesSss) and (not reflectionFresnelMapIsActive) and ((not reflectionFresnelEffectEnabled) or effectiveReflectionIor > 3.0 or metalnessMapIsActive or reflectionMetalnessIsPositive) |
|
), |
|
|
|
— The inputMaterial is expected to be VRayMtl (checked by an assert). |
|
fn convertVRayMtlToCoronaPhysicalMtl inputMaterial =( |
|
assert ((classof inputMaterial) == VRayMtl) |
|
|
|
local outputMaterial = CoronaPhysicalMtl() |
|
outputMaterial.name = inputMaterial.name |
|
|
|
— We have to set roughnessMode first. If we set roughness values first and then switchned |
|
— the roughnessMode, the material would automatically recalculate (change) the roughness |
|
— values. |
|
— |
|
— Note that in VRayMtl, this setting only affects reflection roughness parameter. I.e. it does |
|
— not affect diffuse roughness nor refraction glossiness parameters. |
|
outputMaterial.roughnessMode = if inputMaterial.brdf_useRoughness then ( 0 ) else ( 1 ) |
|
|
|
— Need to explicitly set this because the default is user-configurable and all the following |
|
— computations rely on the assumption that this material uses IoR parameters. |
|
outputMaterial.iorMode = 0 |
|
|
|
local metal = isMetalVRayMtl inputMaterial |
|
|
|
— Basic options |
|
outputMaterial.metalnessMode = if metal then ( 1 ) else ( 0 ) |
|
|
|
— Property «texmap_metalness» is only available in VRayMtl since V-Ray 4. |
|
if hasProperty inputMaterial «texmap_metalness« then ( |
|
outputMaterial.metalnessTexmap = inputMaterial.texmap_metalness |
|
) |
|
|
|
— Property «refraction_thinWalled» is only available in VRayMtl since V-Ray 5. |
|
if hasProperty inputMaterial «refraction_thinWalled« then ( |
|
outputMaterial.useThinMode = inputMaterial.refraction_thinWalled |
|
) |
|
|
|
— Set baseLevel, basecolor, baseTexmap, baseTexmapOn, baseMapAmount. |
|
outputMaterial.baseLevel = 1.0 |
|
— Non-metals do not tint reflections, so in such case we don’t take reflection color into account. |
|
local levelReflect = if metal then ( 1.0 ) else ( 0.0 ) |
|
— If non-metal we use the texmap_reflection for reducing effect of IoR. |
|
local texmapReflection = if metal then ( inputMaterial.texmap_reflection ) else ( undefined ) |
|
local zipMtl1 = ZipMtl inputMaterial.Diffuse «Diffuse« 1.0 inputMaterial.texmap_diffuse inputMaterial.texmap_diffuse_on inputMaterial.texmap_diffuse_multiplier |
|
local zipMtl2 = ZipMtl inputMaterial.Reflection «Reflection« levelReflect texmapReflection inputMaterial.texmap_reflection_on inputMaterial.texmap_reflection_multiplier |
|
local MAP_MAX_AMOUNT = 100.0 |
|
local zeroWeightsLerpBias = if metal then ( 0.5 ) else ( 0.0 ) |
|
zipParams &outputMaterial.basecolor &outputMaterial.baseTexmap &outputMaterial.baseTexmapOn &outputMaterial.baseMapAmount zipMtl1 zipMtl2 MAP_MAX_AMOUNT zeroWeightsLerpBias:zeroWeightsLerpBias |
|
|
|
— Set baseRoughness, baseRoughnessTexmap, baseRoughnessTexmapOn, baseRoughnessMapAmount. |
|
local MIX_OPERATION_SUBTRACT = 1 |
|
— Diffuse roughness is quite a new parameter which has a default value 0. In such case we assume |
|
— that it was not set explicitly by an user and therefore don’t take it into account. |
|
local levelDiffuse = if (mapIsActive inputMaterial.texmap_roughness inputMaterial.texmap_roughness_on inputMaterial.texmap_roughness_multiplier) or (inputMaterial.diffuse_roughness > 0.0) then ( 1.0 ) else ( 0.0 ) |
|
— Metals do not refract light, so in such case we don’t take refraction roughness into account. |
|
local levelRefract = if metal or not (usesRefractionVRayMtl inputMaterial) then ( 0.0 ) else ( 1.0 ) |
|
— inputMaterial.brdf_useRoughness parameter only affects reflection roughness / glossiness |
|
— parameter. It does not affect diffuse roughness nor refraction glossiness parameters. |
|
local roughnessSettingAwareRefractionGlossiness = if inputMaterial.brdf_useRoughness then ( 1.0 — inputMaterial.refraction_glossiness ) else ( inputMaterial.refraction_glossiness ) |
|
local roughnessSettingAwareDiffuseRoughness = if inputMaterial.brdf_useRoughness then ( inputMaterial.diffuse_roughness ) else ( 1.0 — inputMaterial.diffuse_roughness ) |
|
local refractionGlossinessTexture = inputMaterial.texmap_refractionGlossiness |
|
local diffuseRoughnessTexture = inputMaterial.texmap_roughness |
|
if inputMaterial.brdf_useRoughness then ( |
|
— VRayMtl always uses glossiness workflow for its refraction glossiness parameter, |
|
— irrespective of value of inputMaterial.brdf_useRoughness parameter. |
|
if refractionGlossinessTexture != undefined then ( |
|
refractionGlossinessTexture = mapsMix (createCoronaColorNode white «One«) 1.0 refractionGlossinessTexture 1.0 «One_minus_Refraction_glossiness« mixOperation:MIX_OPERATION_SUBTRACT |
|
) |
|
) else ( |
|
— VRayMtl always uses roughness workflow for its diffuse roughness parameter, irrespective of |
|
— value of inputMaterial.brdf_useRoughness parameter. |
|
if diffuseRoughnessTexture != undefined then ( |
|
diffuseRoughnessTexture = mapsMix (createCoronaColorNode white «One«) 1.0 diffuseRoughnessTexture 1.0 «One_minus_Diffuse_roughness« mixOperation:MIX_OPERATION_SUBTRACT |
|
) |
|
) |
|
local zipMtl1 = ZipMtl roughnessSettingAwareDiffuseRoughness «diffuse_roughness« levelDiffuse diffuseRoughnessTexture inputMaterial.texmap_roughness_on inputMaterial.texmap_roughness_multiplier |
|
local zipMtl2 = ZipMtl roughnessSettingAwareRefractionGlossiness «refraction_glossiness« levelRefract refractionGlossinessTexture inputMaterial.texmap_refractionGlossiness_on inputMaterial.texmap_refractionGlossiness_multiplier |
|
|
|
zipParams &outputMaterial.baseRoughness &outputMaterial.baseRoughnessTexmap &outputMaterial.baseRoughnessTexmapOn &outputMaterial.baseRoughnessMapAmount zipMtl1 zipMtl2 MAP_MAX_AMOUNT zeroWeightsLerpBias:0.0 |
|
|
|
if (outputMaterial.baseRoughnessTexmap == undefined and inputMaterial.texmap_reflectionGlossiness == undefined) and (approxEq inputMaterial.reflection_glossiness roughnessSettingAwareRefractionGlossiness) and (approxEq inputMaterial.reflection_glossiness roughnessSettingAwareDiffuseRoughness) then ( |
|
assert (inputMaterial.texmap_refractionGlossiness == undefined) |
|
assert (inputMaterial.texmap_roughness == undefined) |
|
assert (approxEq outputMaterial.baseRoughness inputMaterial.reflection_glossiness) |
|
|
|
) else ( |
|
local zipMtl1 = ZipMtl inputMaterial.reflection_glossiness «reflection_glossiness« 1.0 inputMaterial.texmap_reflectionGlossiness inputMaterial.texmap_reflectionGlossiness_on inputMaterial.texmap_reflectionGlossiness_multiplier |
|
local zipMtl2 = ZipMtl outputMaterial.baseRoughness «diffuse_roughness_and_refraction_glossiness« (levelDiffuse + levelRefract) outputMaterial.baseRoughnessTexmap outputMaterial.baseRoughnessTexmapOn outputMaterial.baseRoughnessMapAmount |
|
|
|
zipParams &outputMaterial.baseRoughness &outputMaterial.baseRoughnessTexmap &outputMaterial.baseRoughnessTexmapOn &outputMaterial.baseRoughnessMapAmount zipMtl1 zipMtl2 MAP_MAX_AMOUNT zeroWeightsLerpBias:0.0 |
|
) |
|
|
|
local GGX = 4 |
|
if inputMaterial.brdf_type != GGX then ( |
|
— Approximation of the vrayBlinnToCoronaGgxTable used in the original Corona Converter script |
|
— we got from Martin Geupel. |
|
local EXPONENT = if inputMaterial.brdf_useRoughness then ( 0.62 ) else ( 1.51 ) |
|
outputMaterial.baseRoughness = outputMaterial.baseRoughness ^ EXPONENT |
|
|
|
if outputMaterial.baseRoughnessTexmap != undefined then ( |
|
outputMaterial.baseRoughnessTexmap = addCoronaColorCorrectNode «Roughness_Adaptation« outputMaterial.baseRoughnessTexmap gamma:(1.0 / EXPONENT) |
|
) |
|
) |
|
|
|
— Set baseIor, baseIorTexmap, baseIorTexmapOn, baseIorMapAmount. |
|
local zipMtl1 = ZipMtl inputMaterial.reflection_IOR «reflection_IOR« 1.0 inputMaterial.texmap_reflectionIOR inputMaterial.texmap_reflectionIOR_on inputMaterial.texmap_reflectionIOR_multiplier |
|
local zipMtl2 = ZipMtl inputMaterial.refraction_ior «refraction_IOR« levelRefract inputMaterial.texmap_refractionIOR inputMaterial.texmap_refractionIOR_on inputMaterial.texmap_refractionIOR_multiplier |
|
local iorUsesMixNode = zipParams &outputMaterial.baseIor &outputMaterial.baseIorTexmap &outputMaterial.baseIorTexmapOn &outputMaterial.baseIorMapAmount zipMtl1 zipMtl2 MAP_MAX_AMOUNT zeroWeightsLerpBias:0.0 |
|
|
|
— If reflection IOR is locked, then its value is the same as value of refraction IOR. |
|
if iorUsesMixNode and inputMaterial.reflection_lockIOR then ( |
|
assert ((classof outputMaterial.baseIorTexmap) == CoronaMix) |
|
|
|
outputMaterial.baseIorTexmap.mixAmount = 1.0 — Take only refraction IOR into account. |
|
) |
|
|
|
— Since CoronaPhysicalMtl does not have a reflection level parameter nor can not use reflection |
|
— level map, the only way to reproduce look of the inputMaterial is by adjusting |
|
— CoronaPhysicalMtl’s IoR by input reflection level (or its IoR map by input reflection level |
|
— map respectively). |
|
local iorUnaffectedByLevelReflect = outputMaterial.baseIor |
|
|
|
local effectiveReflectLevel = (colorToAverageLuminance inputMaterial.Reflection) / MAX_COLOR_VALUE |
|
assert((0.0 <= effectiveReflectLevel) and (effectiveReflectLevel <= 1.0)) |
|
|
|
outputMaterial.baseIor = lerp 1.0 outputMaterial.baseIor effectiveReflectLevel |
|
|
|
— If metal we use the texmap_reflection as a tint for baseColor. |
|
local texmapReflection = if metal then ( undefined ) else ( inputMaterial.texmap_reflection ) |
|
|
|
if (texmapReflection == undefined) and (outputMaterial.baseIorTexmap == undefined) then ( |
|
— Only need to set outputMaterial.baseIor which is already handled. |
|
|
|
) else ( |
|
— Set the output map to max amount and enable it, since in the following cases we will |
|
— account for these parameters in the corresponding shading networks. |
|
outputMaterial.baseIorTexmapOn = true |
|
outputMaterial.baseIorMapAmount = MAP_MAX_AMOUNT |
|
|
|
local MIX_NODE_NAME = «Adjusted_IoR« |
|
|
|
— Note that in the following 3 cases we must use iorUnaffectedByLevelReflect, since we |
|
— further multiply shading networks where this value is used by effectiveReflectLevel. Since |
|
— baseIor already accounts for effectiveReflectLevel if we used it here again, we would |
|
— effectively perform two multiplications by effectiveReflectLevel. |
|
if (texmapReflection == undefined) and (outputMaterial.baseIorTexmap != undefined) and (effectiveReflectLevel < 1.0) then ( |
|
— Adjust CoronaPhysicalMtl’s IoR map values using lerp(1, IoR map, luminance(reflection color)). |
|
|
|
local baseIorMapColorMixOrMap = tryGetMapColorMixOrMap «BaseIor« iorUnaffectedByLevelReflect outputMaterial.baseIorTexmap outputMaterial.baseIorTexmapOn outputMaterial.baseIorMapAmount MAP_MAX_AMOUNT |
|
assert (baseIorMapColorMixOrMap != undefined) |
|
|
|
local effectiveReflectLevelComplement = 1.0 — effectiveReflectLevel |
|
outputMaterial.baseIorTexmap = mapsMix (createCoronaColorNode white «One«) effectiveReflectLevelComplement baseIorMapColorMixOrMap effectiveReflectLevel MIX_NODE_NAME |
|
|
|
) else if (texmapReflection != undefined) and (outputMaterial.baseIorTexmap == undefined) then ( |
|
— Adjust CoronaPhysicalMtl’s IoR value using lerp(1, IoR value, reflection map). |
|
|
|
local reflectMapColorMixOrMap = tryGetMapColorMixOrMap «Reflection« inputMaterial.Reflection texmapReflection inputMaterial.texmap_reflection_on inputMaterial.texmap_reflection_multiplier MAP_MAX_AMOUNT |
|
assert (reflectMapColorMixOrMap != undefined) |
|
|
|
outputMaterial.baseIorTexmap = mapsMix (createCoronaColorNode white «One«) 1.0 (createCoronaColorNode iorUnaffectedByLevelReflect «IoR«) 1.0 MIX_NODE_NAME |
|
outputMaterial.baseIorTexmap.texmapMix = reflectMapColorMixOrMap |
|
|
|
) else if (texmapReflection != undefined) and (outputMaterial.baseIorTexmap != undefined) then ( |
|
— Adjust CoronaPhysicalMtl’s IoR map values using lerp(1, IoR map, reflection map). |
|
|
|
local baseIorMapColorMixOrMap = tryGetMapColorMixOrMap «BaseIor« iorUnaffectedByLevelReflect outputMaterial.baseIorTexmap outputMaterial.baseIorTexmapOn outputMaterial.baseIorMapAmount MAP_MAX_AMOUNT |
|
assert (baseIorMapColorMixOrMap != undefined) |
|
|
|
local reflectMapColorMixOrMap = tryGetMapColorMixOrMap «Reflection« inputMaterial.Reflection texmapReflection inputMaterial.texmap_reflection_on inputMaterial.texmap_reflection_multiplier MAP_MAX_AMOUNT |
|
assert (reflectMapColorMixOrMap != undefined) |
|
|
|
outputMaterial.baseIorTexmap = mapsMix (createCoronaColorNode white «One«) 1.0 baseIorMapColorMixOrMap 1.0 MIX_NODE_NAME |
|
outputMaterial.baseIorTexmap.texmapMix = reflectMapColorMixOrMap |
|
) |
|
) |
|
|
|
— The following step is necessary to prevent potential crashes. See this function’s documentation |
|
— for more detail. Note that we pass to the function the originally computed IoR value, before it |
|
— was adjusted by input reflection level. |
|
setFixedIorValueForFalloffMaps outputMaterial.baseIorTexmap iorUnaffectedByLevelReflect |
|
|
|
— Bump |
|
outputMaterial.baseBumpMapAmount = inputMaterial.texmap_bump_multiplier / MAP_MAX_AMOUNT |
|
outputMaterial.baseBumpTexmap = inputMaterial.texmap_bump |
|
|
|
adjustBaseBumpValueFromVRay &outputMaterial |
|
|
|
— Edge color |
|
if metal then ( |
|
outputMaterial.edgeColor = white |
|
) |
|
|
|
— Anisotropy |
|
outputMaterial.baseAnisotropy = inputMaterial.anisotropy |
|
local LOCAL_AXIS = 0 |
|
— CoronaPhysicalMtl in «Local Axis» mode always orients anisotropy highlights along Z axis, while |
|
— in VRayMtl it is possible to configure which axis is used. |
|
local Z_AXIS = 2 |
|
if (inputMaterial.anisotropy_derivation == LOCAL_AXIS) and (inputMaterial.anisotropy_axis == Z_AXIS) then ( |
|
— In this case VRayMtl stretches reflections horizontally when positive values are used and |
|
— vertically when negative values are used. CoronaPhysicalMtl stretches reflections |
|
— horizontally when negative values are used and vertically when positive values are used. |
|
outputMaterial.baseAnisotropy = —inputMaterial.anisotropy |
|
) |
|
outputMaterial.baseAnisotropyTexmap = inputMaterial.texmap_anisotropy |
|
outputMaterial.baseAnisoRotation = inputMaterial.anisotropy_rotation |
|
outputMaterial.baseAnisoRotationTexmap = inputMaterial.texmap_anisotropy_rotation |
|
|
|
— Translucency |
|
— VRayMtl does not have a «translucency lobe». |
|
|
|
— Refraction |
|
— VRayMtl allows to specify refraction amount per color channel, however CoronaPhysicalMtl does |
|
— not. |
|
local refractionLuminance = (colorToAverageLuminance inputMaterial.Refraction) / MAX_COLOR_VALUE |
|
outputMaterial.refractionAmount = if usesRefractionVRayMtl inputMaterial then ( refractionLuminance ) else ( 0.0 ) |
|
outputMaterial.refractionAmountTexmap = inputMaterial.texmap_refraction |
|
outputMaterial.thinAbsorptionColor = inputMaterial.Refraction |
|
if refractionLuminance > 0.0 then ( |
|
— Compensate for refraction amount. |
|
local r = inputMaterial.Refraction.r / refractionLuminance |
|
local g = inputMaterial.Refraction.g / refractionLuminance |
|
local b = inputMaterial.Refraction.b / refractionLuminance |
|
outputMaterial.thinAbsorptionColor = color r g b |
|
) |
|
outputMaterial.thinAbsorptionTexmap = inputMaterial.texmap_refraction |
|
if outputMaterial.thinAbsorptionTexmap != undefined then ( |
|
— Compensate for refraction amount texture. |
|
local thinAbsorptionTexmapLuminance = addCoronaColorCorrectNode «Luminance« outputMaterial.thinAbsorptionTexmap saturation:—1.0 |
|
local OPERATION_DIVIDE = 3 |
|
outputMaterial.thinAbsorptionTexmap = mapsMix outputMaterial.thinAbsorptionTexmap 1.0 thinAbsorptionTexmapLuminance 1.0 «Compensation« mixOperation:OPERATION_DIVIDE |
|
) |
|
— outputMaterial.useCaustics = VRayMtl does not have such parameter. |
|
outputMaterial.dispersionEnable = inputMaterial.refraction_dispersion_on |
|
outputMaterial.dispersion = inputMaterial.refraction_dispersion |
|
|
|
— Opacity |
|
— outputMaterial.opacityLevel = VRayMtl does not have such parameter. |
|
outputMaterial.opacityCutout = if inputMaterial.option_opacityMode == 1 then ( true ) else ( false ) |
|
— outputMaterial.opacityColor = VRayMtl does not have such parameter. |
|
outputMaterial.opacityTexmap = inputMaterial.texmap_opacity |
|
|
|
— VRayMtl does not provide parameters for controlling opacity. |
|
|
|
— Displacement |
|
outputMaterial.displacementMinimum = 0.0 |
|
outputMaterial.displacementMaximum = inputMaterial.texmap_displacement_multiplier / MAP_MAX_AMOUNT |
|
outputMaterial.displacementTexmap = inputMaterial.texmap_displacement |
|
— outputMaterial.displacementWaterLevelOn = VRayMtl does not have such parameter. |
|
— outputMaterial.displacementWaterLevel = VRayMtl does not have such parameter. |
|
|
|
— Clearcoat layer |
|
|
|
— Clearcoat layer is only available in VRayMtl since V-Ray 5. |
|
local hasClearcoatParameters = hasProperty inputMaterial «coat_amount« |
|
|
|
if hasClearcoatParameters then ( |
|
outputMaterial.clearcoatAmount = inputMaterial.coat_amount |
|
outputMaterial.clearcoatAmountTexmap = inputMaterial.texmap_coat_amount |
|
outputMaterial.clearcoatRoughness = inputMaterial.coat_glossiness |
|
outputMaterial.clearcoatRoughnessTexmap = inputMaterial.texmap_coat_glossiness |
|
if inputMaterial.coat_bump_lock then ( |
|
if inputMaterial.texmap_coat_bump != undefined and inputMaterial.texmap_bump != undefined and inputMaterial.texmap_coat_bump != inputMaterial.texmap_bump then ( |
|
— Preserve the inputMaterial.texmap_coat_bump but do not use it. |
|
local TEXMAP_COAT_BUMP_WEIGHT = 0.0 |
|
local TEXMAP_BUMP_WEIGHT = 1.0 |
|
outputMaterial.clearcoatBumpTexmap = mapsMix inputMaterial.texmap_coat_bump TEXMAP_COAT_BUMP_WEIGHT inputMaterial.texmap_bump TEXMAP_BUMP_WEIGHT «Texmap_coat_bump_and_Texmap_bump« |
|
|
|
) else if inputMaterial.texmap_bump != undefined then ( |
|
outputMaterial.clearcoatBumpTexmap = inputMaterial.texmap_bump |
|
|
|
) else ( |
|
outputMaterial.clearcoatBumpTexmap = inputMaterial.texmap_coat_bump |
|
) |
|
— We could as well try to preserve the inputMaterial.texmap_coat_bump_multiplier, however it |
|
— could make the resulting shading networks more complicated therefore it is probably not |
|
— worth the effort. |
|
outputMaterial.clearcoatBumpMapAmount = inputMaterial.texmap_bump_multiplier / MAP_MAX_AMOUNT |
|
) else ( |
|
outputMaterial.clearcoatBumpMapAmount = inputMaterial.texmap_coat_bump_multiplier / MAP_MAX_AMOUNT |
|
outputMaterial.clearcoatBumpTexmap = inputMaterial.texmap_coat_bump |
|
) |
|
adjustClearcoatBumpValueFromVRay &outputMaterial |
|
|
|
outputMaterial.clearcoatIor = inputMaterial.coat_ior |
|
outputMaterial.clearcoatIorTexmap = inputMaterial.texmap_coat_ior |
|
outputMaterial.clearcoatAbsorptionColor = inputMaterial.coat_color |
|
outputMaterial.clearcoatAbsorptionTexmap = inputMaterial.texmap_coat_color |
|
) |
|
|
|
— Sheen layer |
|
|
|
— Sheen layer is only available in VRayMtl since V-Ray 5. |
|
local hasSheenParameters = hasProperty inputMaterial «sheen_color« |
|
|
|
if hasSheenParameters then ( |
|
local sheenTextureIsActive = mapIsActive inputMaterial.texmap_sheen inputMaterial.texmap_sheen_on inputMaterial.texmap_sheen_multiplier |
|
outputMaterial.sheenAmount = if sheenTextureIsActive or inputMaterial.sheen_color != black then ( 1.0 ) else ( 0.0 ) |
|
— outputMaterial.sheenAmountTexmap = VRayMtl does not have such parameter. |
|
outputMaterial.sheenRoughness = inputMaterial.sheen_glossiness |
|
outputMaterial.sheenRoughnessTexmap = inputMaterial.texmap_sheen_glossiness |
|
outputMaterial.sheenColor = inputMaterial.sheen_color |
|
outputMaterial.sheenColorTexmap = inputMaterial.texmap_sheen |
|
) |
|
|
|
— Media options |
|
|
|
— Property «texmap_refraction_fog» is only available in VRayMtl since V-Ray 2.5. |
|
local hasRefractionFogTextureParameter = hasProperty inputMaterial «texmap_refraction_fog« |
|
|
|
— Property «refraction_fogDepth» is only available in VRayMtl since V-Ray ???. |
|
local hasRefractionFogDepthParameter = hasProperty inputMaterial «refraction_fogDepth« |
|
|
|
— Property «translucency_amount» is only available in VRayMtl since V-Ray ???. |
|
local hasTranslucencyAmountParameter = hasProperty inputMaterial «translucency_amount« |
|
|
|
if 1 <= inputMaterial.translucency_on and inputMaterial.translucency_on <= 5 then ( |
|
— Volumetric scattering |
|
outputMaterial.volumetricAbsorptionColor = inputMaterial.refraction_fogColor |
|
if hasRefractionFogTextureParameter then ( |
|
outputMaterial.volumetricAbsorptionTexmap = inputMaterial.texmap_refraction_fog |
|
) |
|
outputMaterial.volumetricScatteringColor = inputMaterial.translucency_color |
|
outputMaterial.volumetricScatteringTexmap = inputMaterial.texmap_translucent |
|
if hasRefractionFogDepthParameter then ( |
|
outputMaterial.attenuationDistance = inputMaterial.refraction_fogDepth |
|
) |
|
— outputMaterial.scatterDirectionality = VRayMtl does not have such parameter. |
|
— outputMaterial.scatterSingleBounce = VRayMtl does not have such parameter. |
|
if hasTranslucencyAmountParameter then ( |
|
if inputMaterial.translucency_amount < 1.0 then ( |
|
if outputMaterial.volumetricAbsorptionTexmap == undefined then ( |
|
outputMaterial.volumetricAbsorptionTexmap createCoronaColorNode outputMaterial.volumetricAbsorptionColor «VolumetricAbsorptionColor« |
|
) |
|
outputMaterial.volumetricAbsorptionTexmap = addCoronaColorCorrectNode «Translucency« outputMaterial.volumetricAbsorptionTexmap factor:inputMaterial.translucency_amount |
|
) |
|
) |
|
) else if inputMaterial.translucency_on == 6 then ( |
|
— Subsurface scattering |
|
if hasTranslucencyAmountParameter then ( |
|
outputMaterial.sssAmount = inputMaterial.translucency_amount |
|
) |
|
— outputMaterial.sssAmountTexmap = VRayMtl does not have such parameter. |
|
outputMaterial.sssRadius = (colorToAverageLuminance inputMaterial.refraction_fogColor) / MAX_COLOR_VALUE |
|
if hasRefractionFogTextureParameter then ( |
|
outputMaterial.sssRadiusTexmap = inputMaterial.texmap_refraction_fog |
|
) |
|
outputMaterial.sssScatterColor = inputMaterial.translucency_color |
|
outputMaterial.sssScatterTexmap = inputMaterial.texmap_translucent |
|
) |
|
|
|
— Advanced options |
|
|
|
— Self-illumination |
|
local selfIllumTextureIsActive = mapIsActive inputMaterial.texmap_self_illumination inputMaterial.texmap_self_illumination_on inputMaterial.texmap_self_illumination_multiplier |
|
local multiplier = amax #(1.0, inputMaterial.texmap_self_illumination_multiplier / 100.0) — VRayMtl allows to define texture multiplier larger than 100.0 which however CoronaPhysicalMtl does not allow, so we need to compensate for this. |
|
outputMaterial.selfIllumLevel = if selfIllumTextureIsActive or outputMaterial.selfIllumColor != black then ( inputMaterial.selfIllumination_multiplier * multiplier ) else ( 0.0 ) — VRayMtl’s default selfIllumination_multiplier is 1.0. |
|
outputMaterial.selfIllumColor = inputMaterial.selfIllumination |
|
outputMaterial.selfIllumTexmap = inputMaterial.texmap_self_illumination |
|
|
|
— Anisotropy orientation |
|
outputMaterial.anisotropyOrientationMode = inputMaterial.anisotropy_derivation |
|
outputMaterial.anisotropyOrientationUvwChannel = inputMaterial.anisotropy_channel |
|
|
|
— outputMaterial.gBufferOverride = VRayMtl does not have such parameter. |
|
— outputMaterial.alphaMode = VRayMtl does not have such parameter. |
|
— outputMaterial.renderElementPropagation = VRayMtl does not have such parameter. |
|
|
|
outputMaterial.bgOverrideReflectTexmap = inputMaterial.texmap_environment |
|
— outputMaterial.bgOverrideRefractTexmap = VRayMtl does not have such parameter. |
|
|
|
— Maps options |
|
— outputMaterial.baseTexmapOn already handled. |
|
— outputMaterial.baseMapAmount already handled. |
|
— outputMaterial.baseRoughnessTexmapOn already handled. |
|
— outputMaterial.baseRoughnessMapAmount already handled. |
|
outputMaterial.baseAnisotropyTexmapOn = inputMaterial.texmap_anisotropy_on |
|
outputMaterial.baseAnisotropyMapAmount = inputMaterial.texmap_anisotropy_multiplier |
|
outputMaterial.baseAnisoRotationTexmapOn = inputMaterial.texmap_anisotropy_rotation_on |
|
outputMaterial.baseAnisoRotationMapAmount = inputMaterial.texmap_anisotropy_rotation_multiplier |
|
— outputMaterial.baseIorTexmapOn already handled. |
|
— outputMaterial.baseIorMapAmount already handled. |
|
— outputMaterial.edgeColorTexmapOn = VRayMtl does not have such parameter. |
|
— outputMaterial.edgeColorMapAmount = VRayMtl does not have such parameter. |
|
— VRayMtl does not have a «translucency lobe». |
|
|
|
— Property «texmap_metalness_on» is only available in VRayMtl since V-Ray 4. |
|
if hasProperty inputMaterial «texmap_metalness« then ( |
|
outputMaterial.metalnessTexmapOn = inputMaterial.texmap_metalness_on |
|
) |
|
outputMaterial.refractionAmountTexmapOn = inputMaterial.texmap_refraction_on |
|
outputMaterial.refractionAmountMapAmount = inputMaterial.texmap_refraction_multiplier |
|
outputMaterial.thinAbsorptionTexmapOn = inputMaterial.texmap_refraction_on |
|
outputMaterial.thinAbsorptionMapAmount = inputMaterial.texmap_refraction_multiplier |
|
outputMaterial.opacityTexmapOn = inputMaterial.texmap_opacity_on |
|
outputMaterial.opacityMapAmount = inputMaterial.texmap_opacity_multiplier |
|
outputMaterial.selfIllumTexmapOn = inputMaterial.texmap_self_illumination_on |
|
outputMaterial.selfillumMapAmount = inputMaterial.texmap_self_illumination_multiplier |
|
outputMaterial.baseBumpTexmapOn = inputMaterial.texmap_bump_on |
|
outputMaterial.displacementTexmapOn = inputMaterial.texmap_displacement_on |
|
if hasClearcoatParameters then ( |
|
outputMaterial.clearcoatAmountTexmapOn = inputMaterial.texmap_coat_amount_on |
|
outputMaterial.clearcoatAmountMapAmount = inputMaterial.texmap_coat_amount_multiplier |
|
outputMaterial.clearcoatIorTexmapOn = inputMaterial.texmap_coat_ior_on |
|
outputMaterial.clearcoatIorMapAmount = inputMaterial.texmap_coat_ior_multiplier |
|
outputMaterial.clearcoatRoughnessTexmapOn = inputMaterial.texmap_coat_glossiness_on |
|
outputMaterial.clearcoatRoughnessMapAmount = inputMaterial.texmap_coat_glossiness_multiplier |
|
outputMaterial.clearcoatAbsorptionTexmapOn = inputMaterial.texmap_coat_color_on |
|
outputMaterial.clearcoatAbsorptionMapAmount = inputMaterial.texmap_coat_color_multiplier |
|
outputMaterial.clearcoatBumpTexmapOn = if inputMaterial.coat_bump_lock then ( inputMaterial.texmap_bump_on ) else ( inputMaterial.texmap_coat_bump_on ) |
|
) |
|
if hasSheenParameters then ( |
|
— outputMaterial.sheenAmountTexmapOn = VRayMtl does not have such parameter. |
|
— outputMaterial.sheenAmountMapAmount = VRayMtl does not have such parameter. |
|
outputMaterial.sheenColorTexmapOn = inputMaterial.texmap_sheen_on |
|
outputMaterial.sheenColorMapAmount = inputMaterial.texmap_sheen_multiplier |
|
outputMaterial.sheenRoughnessTexmapOn = inputMaterial.texmap_sheen_glossiness_on |
|
outputMaterial.sheenRoughnessMapAmount = inputMaterial.texmap_sheen_glossiness_multiplier |
|
) |
|
if inputMaterial.translucency_on == 6 then ( |
|
— outputMaterial.sssAmountTexmapOn = VRayMtl does not have such parameter. |
|
— outputMaterial.sssAmountMapAmount = VRayMtl does not have such parameter. |
|
if hasRefractionFogTextureParameter then ( |
|
outputMaterial.sssRadiusTexmapOn = inputMaterial.texmap_refraction_fog_on |
|
outputMaterial.sssRadiusMapAmount = inputMaterial.texmap_refraction_fog_multiplier |
|
) |
|
outputMaterial.sssScatterTexmapOn = inputMaterial.texmap_translucent_on |
|
outputMaterial.sssScatterMapAmount = inputMaterial.texmap_translucent_multiplier |
|
) else if 1 <= inputMaterial.translucency_on and inputMaterial.translucency_on <= 5 then ( |
|
if hasRefractionFogTextureParameter then ( |
|
outputMaterial.volumetricAbsorptionTexmapOn = inputMaterial.texmap_refraction_fog_on |
|
outputMaterial.volumetricAbsorptionMapAmount = inputMaterial.texmap_refraction_fog_multiplier |
|
) |
|
outputMaterial.volumetricScatteringTexmapOn = inputMaterial.texmap_translucent_on |
|
outputMaterial.volumetricScatteringMapAmount = inputMaterial.texmap_translucent_multiplier |
|
) |
|
— outputMaterial.bgOverrideReflectTexmapOn = VRayMtl does not have such parameter. |
|
— outputMaterial.bgOverrideRefractTexmapOn = VRayMtl does not have such parameter. |
|
|
|
/*return*/ outputMaterial |
|
), |
|
|
|
fn createCoronaFrontBackNode mapBack mapFront nodeName =( |
|
local frontBackMap = CoronaFrontBack() |
|
frontBackMap.name = nodeName |
|
|
|
frontBackMap.frontTexmap = mapFront |
|
frontBackMap.backTexmap = mapBack |
|
|
|
/*return*/ frontBackMap |
|
), |
|
|
|
— Return value (bool) indicates whether CoronaFrontBack node was used for mixing the input |
|
— parameters. |
|
fn fuse2SidedParams &outputMtlParam &outputMtlParamMap &outputMtlParamMapOn &outputMtlParamMapAmount backMtl frontMtl mtlParamMapMaxAmount =( |
|
outputMtlParam = valuesMix backMtl.param backMtl.paramLevel frontMtl.param frontMtl.paramLevel |
|
|
|
local usesFrontBackNode = false |
|
|
|
backMtl.paramName = capitalizeFirstLetter backMtl.paramName |
|
frontMtl.paramName = capitalizeFirstLetter frontMtl.paramName |
|
|
|
if (backMtl.paramMap == undefined and frontMtl.paramMap == undefined) and (approxEq backMtl.param frontMtl.param) then ( |
|
assert (approxEq outputMtlParam backMtl.param) |
|
assert (approxEq outputMtlParam frontMtl.param) |
|
assert (outputMtlParamMap == undefined) |
|
|
|
) else if (backMtl.paramMap == frontMtl.paramMap) and (approxEq backMtl.param frontMtl.param) then ( |
|
assert (approxEq outputMtlParam backMtl.param) |
|
assert (approxEq outputMtlParam frontMtl.param) |
|
|
|
local effectiveBackMtlMapAmount = computeEffectiveMapWeight backMtl.paramMapOn backMtl.paramMapAmount |
|
local effectiveFrontMtlMapAmount = computeEffectiveMapWeight frontMtl.paramMapOn frontMtl.paramMapAmount |
|
|
|
fn assertions mapColorMixOrMap backMtl frontMtl =( |
|
if ((classof mapColorMixOrMap) == CoronaMix) then ( |
|
assert ((classof mapColorMixOrMap.texmapTop) == CoronaColor) |
|
assert (mapColorMixOrMap.texmapBottom == backMtl.paramMap) |
|
assert (mapColorMixOrMap.texmapBottom == frontMtl.paramMap) |
|
) else ( |
|
assert (mapColorMixOrMap == backMtl.paramMap) |
|
assert (mapColorMixOrMap == frontMtl.paramMap) |
|
) |
|
) |
|
|
|
if (approxEq effectiveBackMtlMapAmount effectiveFrontMtlMapAmount) then ( |
|
outputMtlParamMap = tryGetMapColorMixOrMap backMtl.paramName backMtl.param backMtl.paramMap backMtl.paramMapOn backMtl.paramMapAmount mtlParamMapMaxAmount |
|
assert (outputMtlParamMap != undefined) |
|
|
|
assertions outputMtlParamMap backMtl frontMtl |
|
|
|
) else ( |
|
local backSide = tryGetMapColorMixOrMap backMtl.paramName backMtl.param backMtl.paramMap backMtl.paramMapOn backMtl.paramMapAmount mtlParamMapMaxAmount |
|
assert (backSide != undefined) |
|
|
|
assertions backSide backMtl frontMtl |
|
|
|
local frontSide = tryGetMapColorMixOrMap frontMtl.paramName frontMtl.param frontMtl.paramMap frontMtl.paramMapOn frontMtl.paramMapAmount mtlParamMapMaxAmount |
|
assert (frontSide != undefined) |
|
|
|
assertions frontSide backMtl frontMtl |
|
|
|
local nodeName2Sided = backMtl.paramName + «_and_« + frontMtl.paramName |
|
outputMtlParamMap = createCoronaFrontBackNode backSide frontSide nodeName2Sided |
|
usesFrontBackNode = true |
|
) |
|
) else ( |
|
local backMtlParamColorMixOrColor = tryGetMapColorMixOrMap backMtl.paramName backMtl.param backMtl.paramMap backMtl.paramMapOn backMtl.paramMapAmount mtlParamMapMaxAmount |
|
if backMtlParamColorMixOrColor == undefined then ( |
|
backMtlParamColorMixOrColor = createCoronaColorNode backMtl.param backMtl.paramName |
|
) |
|
|
|
local frontMtlParamColorMixOrColor = tryGetMapColorMixOrMap frontMtl.paramName frontMtl.param frontMtl.paramMap frontMtl.paramMapOn frontMtl.paramMapAmount mtlParamMapMaxAmount |
|
if frontMtlParamColorMixOrColor == undefined then ( |
|
frontMtlParamColorMixOrColor = createCoronaColorNode frontMtl.param frontMtl.paramName |
|
) |
|
|
|
local nodeName2Sided = backMtl.paramName + «_and_« + frontMtl.paramName |
|
outputMtlParamMap = createCoronaFrontBackNode backMtlParamColorMixOrColor frontMtlParamColorMixOrColor nodeName2Sided |
|
usesFrontBackNode = true |
|
) |
|
— Must be set to max amount and be on, since we often plug the original colors to the material as |
|
— a CoronaColor node and use the original map amount and map on parameters to blend this map with |
|
— original textures (if present). |
|
outputMtlParamMapAmount = mtlParamMapMaxAmount |
|
outputMtlParamMapOn = true |
|
|
|
/*return*/ usesFrontBackNode |
|
), |
|
|
|
fn copyVRay2SidedMtlTranslucencySettingsToCoronaPhysicalMtl vray2SidedMat &coronaPhysicalMat =( |
|
assert((classof vray2SidedMat) == VRay2SidedMtl) |
|
assert((classof coronaPhysicalMat) == CoronaPhysicalMtl) |
|
|
|
— VRayMtl allows to specify translucency fraction per color channel, however coronaPhysicalMat |
|
— does not. |
|
coronaPhysicalMat.translucencyFraction = (colorToAverageLuminance vray2SidedMat.translucency) / MAX_COLOR_VALUE |
|
|
|
if vray2SidedMat.texmap_translucency != undefined then ( |
|
local colorWeight = 100.0 — vray2SidedMat.texmap_translucency_multiplier |
|
local COLOR_NODE_NAME = «TranslucencyFraction« |
|
local MIX_NODE_NAME = «TranslucencyFractionMap_and_TranslucencyFraction« |
|
coronaPhysicalMat.translucencyFractionTexmap = mapColorMix vray2SidedMat.texmap_translucency vray2SidedMat.texmap_translucency_multiplier vray2SidedMat.translucency colorWeight COLOR_NODE_NAME MIX_NODE_NAME |
|
) |
|
— The vray2SidedMat’s texmap_translucency_multiplier is already accounted for in a corresponding |
|
— CoronaMix node (see above). |
|
coronaPhysicalMat.translucencyFractionTexmapOn = true |
|
coronaPhysicalMat.translucencyFractionMapAmount = 100.0 |
|
|
|
— coronaPhysicalMat.translucencyColor = No need to worry about this, since it will be overriden by coronaPhysicalMat.translucencyColorTexmap, coronaPhysicalMat.translucencyColorTexmapOn will be true and coronaPhysicalMat.translucencyColorMapAmount will be 100.0. |
|
|
|
if coronaPhysicalMat.baseTexmap == undefined then ( |
|
coronaPhysicalMat.baseTexmap = createCoronaColorNode coronaPhysicalMat.basecolor «BaseColor« |
|
) |
|
|
|
— VRayMtl uses base color of the opposite side as a translucency color. |
|
if (classof coronaPhysicalMat.baseTexmap) == CoronaFrontBack then ( |
|
local NODE_NAME = «Switched_« + coronaPhysicalMat.baseTexmap.name |
|
coronaPhysicalMat.translucencyColorTexmap = createCoronaFrontBackNode coronaPhysicalMat.baseTexmap.frontTexmap coronaPhysicalMat.baseTexmap.backTexmap NODE_NAME |
|
) else ( |
|
coronaPhysicalMat.translucencyColorTexmap = coronaPhysicalMat.baseTexmap |
|
) |
|
coronaPhysicalMat.translucencyColorTexmapOn = true |
|
coronaPhysicalMat.translucencyColorMapAmount = 100.0 |
|
|
|
assert(coronaPhysicalMat.translucencyColorTexmap != undefined) |
|
|
|
if vray2SidedMat.mult_by_front_diffuse then ( |
|
— Since we mentioned above that VRayMtl uses base color of the opposite side as a |
|
— translucency color we can do this: |
|
local oppositeSide = coronaPhysicalMat.baseTexmap |
|
local NODE_NAME = «Multiply_by_opposite_side« |
|
local MIX_OPERATION_MULTIPLY = 2 |
|
coronaPhysicalMat.translucencyColorTexmap = mapsMix coronaPhysicalMat.translucencyColorTexmap 1.0 oppositeSide 1.0 NODE_NAME mixOperation:MIX_OPERATION_MULTIPLY |
|
) |
|
), |
|
|
|
— If the input VRay2SidedMtl has two materials assigned and both of them are (or are convertible to) |
|
— CoronaPhysicalMtl, this function attempts to create a new CoronaPhysicalMtl with CoronaFrontBack |
|
— nodes replicating look of the original VRay2SidedMtl. If the input VRay2SidedMtl has only one |
|
— material assigned, then the assigned material is returned. If no material is assigned, this |
|
— function returns a default CoronaPhysicalMtl. Otherwise the material connected to the front slot is |
|
— returned. |
|
— The inputMaterial is expected to be VRay2SidedMtl (checked by an assert). |
|
fn processVRay2SidedMtl inputMaterial =( |
|
assert ((classof inputMaterial) == VRay2SidedMtl) |
|
|
|
if (inputMaterial.frontMtl == undefined) and ((inputMaterial.backMtl == undefined) or (not inputMaterial.backMtlOn)) then ( |
|
/*return*/ createDefaultCoronaPhysicalMtl inputMaterial.name |
|
|
|
) else if inputMaterial.frontMtl == undefined then ( |
|
local outputMaterial = inputMaterial.backMtl |
|
|
|
if ((classof outputMaterial) == CoronaPhysicalMtl) then ( |
|
outputMaterial.useThinMode = true |
|
copyVRay2SidedMtlTranslucencySettingsToCoronaPhysicalMtl inputMaterial &outputMaterial |
|
) |
|
|
|
/*return*/ outputMaterial |
|
|
|
) else if (inputMaterial.backMtl == undefined) or (not inputMaterial.backMtlOn) then ( |
|
local outputMaterial = inputMaterial.frontMtl |
|
|
|
if ((classof outputMaterial) == CoronaPhysicalMtl) then ( |
|
outputMaterial.useThinMode = true |
|
copyVRay2SidedMtlTranslucencySettingsToCoronaPhysicalMtl inputMaterial &outputMaterial |
|
) |
|
|
|
/*return*/ outputMaterial |
|
|
|
) else ( |
|
if ((classof inputMaterial.frontMtl) == CoronaPhysicalMtl) and ((classof inputMaterial.backMtl) == CoronaPhysicalMtl) then ( |
|
local outputMaterial = CoronaPhysicalMtl() |
|
outputMaterial.name = inputMaterial.name |
|
|
|
— If we set roughness values first and then switchned the roughnessMode, the material |
|
— would automatically recalculate (change) the roughness values. |
|
outputMaterial.roughnessMode = inputMaterial.frontMtl.roughnessMode — This value is hand picked, since it can not be interpolated. |
|
|
|
— Need to explicitly set this because the default is user-configurable and all the |
|
— following computations rely on the assumption that this material uses IoR parameters. |
|
outputMaterial.iorMode = 0 |
|
|
|
— Attempts to replicate look of parameter of the original VRay2SidedMtl in |
|
— CoronaPhysicalMtl. |
|
— Return value (bool) indicates whether CoronaFrontBack node was used for mixing input |
|
— parameters of the VRay2SidedMtl. |
|
fn set2SidedParam &outputMaterial inputMaterial paramName paramTexmapName paramTexmapOnName paramMapAmountName =( |
|
local PARAM_LEVEL = 1.0 |
|
local MAP_MAX_AMOUNT = 100.0 |
|
|
|
local backParamMapAmount = if paramMapAmountName != undefined then ( getProperty inputMaterial.backMtl paramMapAmountName ) else ( MAP_MAX_AMOUNT ) |
|
local backMtl = ZipMtl (getProperty inputMaterial.backMtl paramName) paramName PARAM_LEVEL (getProperty inputMaterial.backMtl paramTexmapName) (getProperty inputMaterial.backMtl paramTexmapOnName) backParamMapAmount |
|
|
|
local frontParamMapAmount = if paramMapAmountName != undefined then ( getProperty inputMaterial.frontMtl paramMapAmountName ) else ( MAP_MAX_AMOUNT ) |
|
local frontMtl = ZipMtl (getProperty inputMaterial.frontMtl paramName) paramName PARAM_LEVEL (getProperty inputMaterial.frontMtl paramTexmapName) (getProperty inputMaterial.frontMtl paramTexmapOnName) frontParamMapAmount |
|
|
|
local param = getProperty outputMaterial paramName |
|
local paramTexmap = getProperty outputMaterial paramTexmapName |
|
local paramTexmapOn = getProperty outputMaterial paramTexmapOnName |
|
local paramMapAmount = if paramMapAmountName != undefined then ( getProperty outputMaterial paramMapAmountName ) else ( 0.0 ) — If undefined, then we do not care about value of this variable. |
|
|
|
local retval = fuse2SidedParams ¶m ¶mTexmap ¶mTexmapOn ¶mMapAmount backMtl frontMtl MAP_MAX_AMOUNT |
|
|
|
setProperty &outputMaterial paramName param |
|
setProperty &outputMaterial paramTexmapName paramTexmap |
|
setProperty &outputMaterial paramTexmapOnName paramTexmapOn |
|
|
|
if paramMapAmountName != undefined then ( |
|
setProperty &outputMaterial paramMapAmountName paramMapAmount |
|
) |
|
|
|
/*return*/ retval |
|
) |
|
|
|
— Basic options |
|
|
|
set2SidedParam &outputMaterial inputMaterial «metalnessMode« «metalnessTexmap« «metalnessTexmapOn« undefined |
|
|
|
outputMaterial.useThinMode = true |
|
|
|
— The individual levels are set more precisely via CoronaColorCorrect nodes few lines |
|
— later. |
|
outputMaterial.baseLevel = 1.0 |
|
local baseColorUsesFrontBackNode = set2SidedParam &outputMaterial inputMaterial «basecolor« «baseTexmap« «baseTexmapOn« «baseMapAmount« |
|
|
|
if (not baseColorUsesFrontBackNode) and (inputMaterial.backMtl.baseLevel != inputMaterial.frontMtl.baseLevel) then ( |
|
assert (outputMaterial.basecolor == inputMaterial.backMtl.basecolor) |
|
assert (outputMaterial.basecolor == inputMaterial.frontMtl.basecolor) |
|
assert (outputMaterial.baseTexmap == undefined) |
|
|
|
local baseColorNode = createCoronaColorNode outputMaterial.basecolor «BaseColor« |
|
outputMaterial.baseTexmap = createCoronaFrontBackNode baseColorNode baseColorNode «FrontBaseColor_and_BackBaseColor« |
|
baseColorUsesFrontBackNode = true |
|
) |
|
|
|
if baseColorUsesFrontBackNode then ( |
|
assert ((classof outputMaterial.baseTexmap) == CoronaFrontBack) |
|
|
|
if inputMaterial.backMtl.baseLevel < 1.0 then ( |
|
outputMaterial.baseTexmap.backTexmap = addCoronaColorCorrectNode «BaseLevel_Adjustment« outputMaterial.baseTexmap.backTexmap factor:inputMaterial.backMtl.baseLevel |
|
) |
|
if inputMaterial.frontMtl.baseLevel < 1.0 then ( |
|
outputMaterial.baseTexmap.frontTexmap = addCoronaColorCorrectNode «BaseLevel_Adjustment« outputMaterial.baseTexmap.frontTexmap factor:inputMaterial.frontMtl.baseLevel |
|
) |
|
) else ( |
|
assert (outputMaterial.basecolor == inputMaterial.backMtl.basecolor) |
|
assert (outputMaterial.basecolor == inputMaterial.frontMtl.basecolor) |
|
assert (inputMaterial.backMtl.baseLevel == inputMaterial.frontMtl.baseLevel) |
|
|
|
outputMaterial.baseLevel = inputMaterial.frontMtl.baseLevel |
|
) |
|
|
|
set2SidedParam &outputMaterial inputMaterial «baseRoughness« «baseRoughnessTexmap« «baseRoughnessTexmapOn« «baseRoughnessMapAmount« |
|
|
|
set2SidedParam &outputMaterial inputMaterial «baseIor« «baseIorTexmap« «baseIorTexmapOn« «baseIorMapAmount« |
|
|
|
set2SidedParam &outputMaterial inputMaterial «baseBumpMapAmount« «baseBumpTexmap« «baseBumpTexmapOn« undefined |
|
|
|
set2SidedParam &outputMaterial inputMaterial «edgeColor« «edgeColorTexmap« «edgeColorTexmapOn« «edgeColorMapAmount« |
|
|
|
— Anisotropy |
|
set2SidedParam &outputMaterial inputMaterial «baseAnisotropy« «baseAnisotropyTexmap« «baseAnisotropyTexmapOn« «baseAnisotropyMapAmount« |
|
|
|
set2SidedParam &outputMaterial inputMaterial «baseAnisoRotation« «baseAnisoRotationTexmap« «baseAnisoRotationTexmapOn« «baseAnisoRotationMapAmount« |
|
|
|
— Translucency |
|
copyVRay2SidedMtlTranslucencySettingsToCoronaPhysicalMtl inputMaterial &outputMaterial |
|
|
|
— Refraction |
|
set2SidedParam &outputMaterial inputMaterial «refractionAmount« «refractionAmountTexmap« «refractionAmountTexmapOn« «refractionAmountMapAmount« |
|
|
|
set2SidedParam &outputMaterial inputMaterial «thinAbsorptionColor« «thinAbsorptionTexmap« «thinAbsorptionTexmapOn« «thinAbsorptionMapAmount« |
|
|
|
outputMaterial.useCaustics = inputMaterial.backMtl.useCaustics or inputMaterial.frontMtl.useCaustics |
|
outputMaterial.dispersionEnable = inputMaterial.backMtl.dispersionEnable or inputMaterial.frontMtl.dispersionEnable |
|
outputMaterial.dispersion = (inputMaterial.backMtl.dispersion + inputMaterial.frontMtl.dispersion) * 0.5 |
|
|
|
— Opacity |
|
outputMaterial.opacityLevel = (inputMaterial.backMtl.opacityLevel + inputMaterial.frontMtl.opacityLevel) * 0.5 |
|
outputMaterial.opacityCutout = inputMaterial.backMtl.opacityCutout or inputMaterial.frontMtl.opacityCutout |
|
set2SidedParam &outputMaterial inputMaterial «opacityColor« «opacityTexmap« «opacityTexmapOn« «opacityMapAmount« |
|
|
|
— Displacement |
|
outputMaterial.displacementMinimum = (inputMaterial.backMtl.displacementMinimum + inputMaterial.frontMtl.displacementMinimum) * 0.5 |
|
outputMaterial.displacementMaximum = (inputMaterial.backMtl.displacementMaximum + inputMaterial.frontMtl.displacementMaximum) * 0.5 |
|
|
|
if inputMaterial.backMtl.displacementTexmap != undefined and inputMaterial.frontMtl.displacementTexmap != undefined then ( |
|
local backWeight = if inputMaterial.backMtl.displacementTexmapOn then ( 1.0 ) else ( 0.0 ) |
|
local frontWeight = if inputMaterial.frontMtl.displacementTexmapOn then ( 1.0 ) else ( 0.0 ) |
|
local MIX_NODE_NAME = «BackDisplacementMap_and_FrontDisplacementMap« |
|
outputMaterial.displacementTexmap = mapsMix inputMaterial.backMtl.displacementTexmap backWeight inputMaterial.frontMtl.displacementTexmap frontWeight MIX_NODE_NAME |
|
|
|
) else if inputMaterial.backMtl.displacementTexmap != undefined then ( |
|
outputMaterial.displacementTexmap = inputMaterial.backMtl.displacementTexmap |
|
|
|
) else if inputMaterial.frontMtl.displacementTexmap != undefined then ( |
|
outputMaterial.displacementTexmap = inputMaterial.frontMtl.displacementTexmap |
|
) |
|
outputMaterial.displacementWaterLevelOn = inputMaterial.backMtl.displacementWaterLevelOn or inputMaterial.frontMtl.displacementWaterLevelOn |
|
outputMaterial.displacementWaterLevel = (inputMaterial.backMtl.displacementWaterLevel + inputMaterial.frontMtl.displacementWaterLevel) * 0.5 |
|
|
|
— Clearcoat layer |
|
set2SidedParam &outputMaterial inputMaterial «clearcoatAmount« «clearcoatAmountTexmap« «clearcoatAmountTexmapOn« «clearcoatAmountMapAmount« |
|
|
|
set2SidedParam &outputMaterial inputMaterial «clearcoatIor« «clearcoatIorTexmap« «clearcoatIorTexmapOn« «clearcoatIorMapAmount« |
|
|
|
set2SidedParam &outputMaterial inputMaterial «clearcoatRoughness« «clearcoatRoughnessTexmap« «clearcoatRoughnessTexmapOn« «clearcoatRoughnessMapAmount« |
|
|
|
set2SidedParam &outputMaterial inputMaterial «clearcoatAbsorptionColor« «clearcoatAbsorptionTexmap« «clearcoatAbsorptionTexmapOn« «clearcoatAbsorptionMapAmount« |
|
|
|
set2SidedParam &outputMaterial inputMaterial «clearcoatBumpMapAmount« «clearcoatBumpTexmap« «clearcoatBumpTexmapOn« undefined |
|
|
|
— Sheen layer |
|
set2SidedParam &outputMaterial inputMaterial «sheenAmount« «sheenAmountTexmap« «sssAmountTexmapOn« «sssAmountMapAmount« |
|
|
|
set2SidedParam &outputMaterial inputMaterial «sheenColor« «sheenColorTexmap« «sheenColorTexmapOn« «sheenColorMapAmount« |
|
|
|
set2SidedParam &outputMaterial inputMaterial «sheenRoughness« «sheenRoughnessTexmap« «sheenRoughnessTexmapOn« «sheenRoughnessMapAmount« |
|
|
|
— Media options |
|
|
|
— Volumetric scattering |
|
set2SidedParam &outputMaterial inputMaterial «volumetricAbsorptionColor« «volumetricAbsorptionTexmap« «volumetricAbsorptionTexmapOn« «volumetricAbsorptionMapAmount« |
|
|
|
set2SidedParam &outputMaterial inputMaterial «volumetricScatteringColor« «volumetricScatteringTexmap« «volumetricScatteringTexmapOn« «volumetricScatteringMapAmount« |
|
|
|
outputMaterial.attenuationDistance = (inputMaterial.backMtl.attenuationDistance + inputMaterial.frontMtl.attenuationDistance) * 0.5 |
|
outputMaterial.scatterDirectionality = (inputMaterial.backMtl.scatterDirectionality + inputMaterial.frontMtl.scatterDirectionality) * 0.5 |
|
|
|
outputMaterial.scatterSingleBounce = inputMaterial.backMtl.scatterSingleBounce or inputMaterial.frontMtl.scatterSingleBounce |
|
|
|
— Subsurface scattering |
|
set2SidedParam &outputMaterial inputMaterial «sssAmount« «sssAmountTexmap« «sssAmountTexmapOn« «sssAmountMapAmount« |
|
|
|
set2SidedParam &outputMaterial inputMaterial «sssRadius« «sssRadiusTexmap« «sssRadiusTexmapOn« «sssRadiusMapAmount« |
|
|
|
set2SidedParam &outputMaterial inputMaterial «sssScatterColor« «sssScatterTexmap« «sssScatterTexmapOn« «sssScatterMapAmount« |
|
|
|
— Advanced options |
|
|
|
— Self-illumination |
|
— The individual levels are set more precisely via CoronaColorCorrect nodes few lines |
|
— later. |
|
outputMaterial.selfIllumLevel = 1.0 |
|
local selfIllumColorUsesFrontBackNode = set2SidedParam &outputMaterial inputMaterial «selfIllumColor« «selfIllumTexmap« «selfIllumTexmapOn« «selfillumMapAmount« |
|
|
|
if (not selfIllumColorUsesFrontBackNode) and (inputMaterial.backMtl.selfIllumLevel != inputMaterial.frontMtl.selfIllumLevel) then ( |
|
assert (outputMaterial.selfIllumColor == inputMaterial.backMtl.selfIllumColor) |
|
assert (outputMaterial.selfIllumColor == inputMaterial.frontMtl.selfIllumColor) |
|
assert (outputMaterial.selfIllumTexmap == undefined) |
|
|
|
local selfIllumColorNode = createCoronaColorNode outputMaterial.selfIllumColor «SelfIllumColor« |
|
outputMaterial.selfIllumTexmap = createCoronaFrontBackNode selfIllumColorNode selfIllumColorNode nodeName |
|
selfIllumColorUsesFrontBackNode = true |
|
) |
|
|
|
if selfIllumColorUsesFrontBackNode then ( |
|
assert ((classof outputMaterial.selfIllumColor) == CoronaFrontBack) |
|
|
|
if inputMaterial.backMtl.selfIllumLevel < 1.0 then ( |
|
outputMaterial.selfIllumColor.backTexmap = addCoronaColorCorrectNode «SelfIlluminationLevel_Adjustment« outputMaterial.selfIllumColor.backTexmap factor:inputMaterial.backMtl.selfIllumLevel |
|
) |
|
if inputMaterial.frontMtl.selfIllumLevel < 1.0 then ( |
|
outputMaterial.selfIllumColor.frontTexmap = addCoronaColorCorrectNode «SelfIlluminationLevel_Adjustment« outputMaterial.selfIllumColor.frontTexmap factor:inputMaterial.frontMtl.selfIllumLevel |
|
) |
|
) else ( |
|
assert (outputMaterial.selfIllumColor == inputMaterial.backMtl.selfIllumColor) |
|
assert (outputMaterial.selfIllumColor == inputMaterial.frontMtl.selfIllumColor) |
|
assert (inputMaterial.backMtl.selfIllumLevel == inputMaterial.frontMtl.selfIllumLevel) |
|
assert (outputMaterial.selfIllumTexmap == undefined) |
|
|
|
outputMaterial.selfIllumLevel = inputMaterial.frontMtl.selfIllumLevel |
|
) |
|
|
|
— All of the following values are hand picked, since they can not be interpolated. |
|
|
|
— Anisotropy orientation |
|
outputMaterial.anisotropyOrientationMode = inputMaterial.frontMtl.anisotropyOrientationMode |
|
outputMaterial.anisotropyOrientationUvwChannel = inputMaterial.frontMtl.anisotropyOrientationUvwChannel |
|
|
|
outputMaterial.gBufferOverride = inputMaterial.frontMtl.gBufferOverride |
|
outputMaterial.alphaMode = inputMaterial.frontMtl.alphaMode |
|
outputMaterial.renderElementPropagation = inputMaterial.frontMtl.renderElementPropagation |
|
|
|
outputMaterial.bgOverrideReflectTexmap = inputMaterial.frontMtl.bgOverrideReflectTexmap |
|
outputMaterial.bgOverrideRefractTexmap = inputMaterial.frontMtl.bgOverrideRefractTexmap |
|
|
|
/*return*/ outputMaterial |
|
) else ( |
|
assert ((inputMaterial.frontMtl != undefined) and (inputMaterial.backMtl != undefined)) |
|
|
|
local outputMaterial = inputMaterial.frontMtl |
|
|
|
if ((classof outputMaterial) == CoronaPhysicalMtl) then ( |
|
outputMaterial.useThinMode = true |
|
copyVRay2SidedMtlTranslucencySettingsToCoronaPhysicalMtl inputMaterial &outputMaterial |
|
) |
|
|
|
/*return*/ outputMaterial |
|
) |
|
) |
|
), |
|
|
|
— If the inputMaterial is a material, then this function attempts to convert it to native Corona |
|
— material. Otherwise the inputMaterial is returned without any modifications. |
|
fn convertToNativeCoronaMtl inputMaterial &problematicMtls processTextureMaps:true =( |
|
if ((superclassof inputMaterial) != material) then ( |
|
/*return*/ inputMaterial |
|
) else ( |
|
— If we have already converted this material, return the converted instance. |
|
local index = findItem converterTempData.originalMaterials inputMaterial |
|
if index > 0 then ( |
|
/*return*/ converterTempData.newMaterials[index] |
|
) else ( |
|
— Recursively convert also inputMaterial’s sub-materials, if any. |
|
for index = 1 to (getNumSubMtls inputMaterial) do ( |
|
setSubMtl inputMaterial index (convertToNativeCoronaMtl (getSubMtl inputMaterial index) &problematicMtls processTextureMaps:processTextureMaps) |
|
) |
|
|
|
— Recursively convert also inputMaterial’s texture maps, if any. |
|
if processTextureMaps do ( |
|
for index = 1 to (getNumSubTexmaps inputMaterial) do ( |
|
local originalMap = getSubTexmap inputMaterial index |
|
local newMap = convertToCoronaBitmap originalMap |
|
if newMap != #NoReplacement then ( |
|
— If we didn’t call our fixed version of replaceInstances() function here, but tried |
|
— to replace material instances (including all their connected nodes), using |
|
— MAXScript’s replaceInstances() function (which has a known bug), we might end up |
|
— with some duplicate shading nodes (e.g. VRayColor -> CoronaColor, VRayCompText -> |
|
— CoronaMix etc.). |
|
if originalMap != undefined and newMap != undefined and originalMap != newMap then ( |
|
converterTools.replaceMapInstances originalMap newMap |
|
) |
|
setSubTexmap inputMaterial index newMap |
|
) |
|
) |
|
) |
|
|
|
local intermediateMaterial = convertToCoronaLegacyMtl inputMaterial |
|
|
|
local outputMaterial = case (classof intermediateMaterial) of ( |
|
CoronaLegacyMtl: convertCoronaLegacyMtlToCoronaPhysicalMtl intermediateMaterial matConvMethods.owner.converterSettings.translucencyEnablesThinShell &problematicMtls |
|
Shellac: matConvMethods.convertShellacToCoronaLayeredMtl intermediateMaterial |
|
VRay2SidedMtl: processVRay2SidedMtl intermediateMaterial |
|
VRayBlendMtl: matConvMethods.convertVRayBlendMtlToCoronaLayeredMtl intermediateMaterial |
|
VRayBumpMtl: matConvMethods.unwrapVRayBumpMtl intermediateMaterial |
|
VRayFastSSS: matConvMethods.convertVRayFastSSSToCoronaPhysicalMtl intermediateMaterial |
|
VRayHairMtl: matConvMethods.convertVRayHairMtlToCoronaHairMtl intermediateMaterial |
|
VRayLightMtl: matConvMethods.convertVRayLightMtlToCoronaLightMtl intermediateMaterial |
|
VRayMtl: convertVRayMtlToCoronaPhysicalMtl intermediateMaterial |
|
VrayMtlWrapper: matConvMethods.unwrapVRayMtlWrapper intermediateMaterial |
|
VrayOverrideMtl: matConvMethods.convertVRayOverrideMtlToCoronaRaySwitchMtl intermediateMaterial |
|
VRayCarPaintMtl: errorCatching matConvMethods.convertFrom_VRayCarPaintMtl inputMaterial |
|
VRayFastSSS2: errorCatching matConvMethods.convertFrom_VRayFastSSS2 inputMaterial |
|
VRaySkinMtl: errorCatching matConvMethods.convertFrom_VRaySkinMtl inputMaterial |
|
Car_Paint_Material__mi: errorCatching matConvMethods.convertFrom_MRCarPaintMaterial inputMaterial |
|
|
|
— The following materials are not very widely used, therefore we do not have specialized |
|
— conversion functions implemented and replace them with a default CoronaPhysicalMtl instead. |
|
fR_Glass: createDefaultCoronaPhysicalMtl intermediateMaterial.name |
|
fR_Metal: createDefaultCoronaPhysicalMtl intermediateMaterial.name |
|
RaytraceMaterial: createDefaultCoronaPhysicalMtl intermediateMaterial.name |
|
|
|
default: intermediateMaterial |
|
) |
|
|
|
— If the function convertToCoronaLegacyMtl() succeeded, then the function |
|
— convertCoronaLegacyMtlToCoronaPhysicalMtl() is also expected to succeed. |
|
if ((classof intermediateMaterial) != (classof inputMaterial)) then ( |
|
assert((classof intermediateMaterial) == CoronaLegacyMtl) |
|
assert((classof outputMaterial) == CoronaPhysicalMtl) |
|
) |
|
|
|
— If the conversion was successful. |
|
if outputMaterial != inputMaterial then ( |
|
if matConvMethods.owner.converterSettings.addCoronaPrefix then ( |
|
outputMaterial.name = matConvMethods.owner.converterSettings.userPrefixStr + outputMaterial.name |
|
) |
|
|
|
— Copy Material ID channel. |
|
outputMaterial.effectsChannel = inputMaterial.effectsChannel |
|
|
|
— Copy Material Editor specific options. |
|
— Based on: https://forums.cgsociety.org/t/maxscript-for-displaying-material-background-preview-in-slate-material-editor/2050175 |
|
local mtlEditFlags = getMTLMEditFlags inputMaterial |
|
setMTLMEditFlags outputMaterial mtlEditFlags |
|
|
|
— Add the material to the list of converted materials. |
|
append converterTempData.originalMaterials inputMaterial |
|
append converterTempData.newMaterials outputMaterial |
|
|
|
if (classof outputMaterial) == CoronaPhysicalMtl then ( |
|
checkCommonConversionProblems outputMaterial &problematicMtls |
|
) |
|
) |
|
|
|
/*return*/ outputMaterial |
|
) |
|
) |
|
), |
|
|
|
fn createCoronaLights orig_light =( |
|
if ((superclassof orig_light) != light) then ( |
|
/*return*/ orig_light — Check if this is a light — if not, just return it. |
|
) else ( |
|
local i = findItem converterTempData.orig_lights orig_light — check if we have already converted this light |
|
|
|
if i > 0 then ( |
|
/*return*/ converterTempData.new_lights[i] — If it is a light, convert it. |
|
) else ( |
|
local cls = classof orig_light |
|
local new_light = case cls of ( |
|
Free_Light: errorCatching lightConvMethods.convertFrom_StandardLights orig_light |
|
Free_Linear: errorCatching lightConvMethods.convertFrom_StandardLights orig_light |
|
Free_Area: errorCatching lightConvMethods.convertFrom_StandardLights orig_light |
|
Free_Disc: errorCatching lightConvMethods.convertFrom_StandardLights orig_light |
|
Free_Sphere: errorCatching lightConvMethods.convertFrom_StandardLights orig_light |
|
Free_Cylinder: errorCatching lightConvMethods.convertFrom_StandardLights orig_light |
|
Target_Light: errorCatching lightConvMethods.convertFrom_StandardLights orig_light |
|
Target_Linear: errorCatching lightConvMethods.convertFrom_StandardLights orig_light |
|
Target_Area: errorCatching lightConvMethods.convertFrom_StandardLights orig_light |
|
Target_Disc: errorCatching lightConvMethods.convertFrom_StandardLights orig_light |
|
Target_Sphere: errorCatching lightConvMethods.convertFrom_StandardLights orig_light |
|
Target_Cylinder: errorCatching lightConvMethods.convertFrom_StandardLights orig_light |
|
|
|
TargetDirectionallight: errorCatching lightConvMethods.convertFrom_StandardLights orig_light |
|
freeSpot: errorCatching lightConvMethods.convertFrom_StandardLights orig_light |
|
Directionallight: errorCatching lightConvMethods.convertFrom_StandardLights orig_light |
|
Omnilight: errorCatching lightConvMethods.convertFrom_StandardLights orig_light |
|
targetSpot: errorCatching lightConvMethods.convertFrom_StandardLights orig_light |
|
|
|
VrayLight: errorCatching lightConvMethods.convertFrom_VrayLight orig_light |
|
VRayIES: errorCatching lightConvMethods.convertFrom_VrayIES orig_light |
|
VraySun: errorCatching lightConvMethods.convertFrom_VraySun orig_light |
|
miAreaLight: errorCatching lightConvMethods.convertFrom_miAreaLight orig_light |
|
miAreaLightomni: errorCatching lightConvMethods.convertFrom_miAreaLight orig_light |
|
mr_Sky_Portal: errorCatching lightConvMethods.convertMrSkyPortalToCoronaLight orig_light |
|
RectLight: errorCatching lightConvMethods.convertFrom_fRRectLight orig_light |
|
|
|
default: orig_light |
|
) |
|
|
|
if new_light != orig_light then ( — if converted, add to the list of converted lights |
|
append converterTempData.orig_lights orig_light |
|
append converterTempData.new_lights new_light |
|
) |
|
|
|
/*return*/ new_light |
|
) |
|
) |
|
), |
|
|
|
fn cleanConversionData =( |
|
converterTempData.originalMaterials = #() |
|
converterTempData.newMaterials = #() |
|
converterTempData.originalMaps = #() |
|
converterTempData.newMaps = #() |
|
converterTempData.orig_lights = #() |
|
converterTempData.new_lights = #() |
|
|
|
if converterTempData.AD_mats_found then ( |
|
selectionSets[«converted_AD_mtls«] = converterTempData.foundAdskMtls |
|
converterTempData.foundAdskMtls = #() |
|
scenematerialsUpdateHack() |
|
converterTempData.AD_mats_found = false |
|
|
|
local warningMessage = «Autodesk Materials were used in this scene and have been converted, it is STRONGLY recommended to check all those materials before rendering! nObjects using these Materials have been added to a «converted_AD_mtls« selection set« |
|
if not converterSettings.silent do ( |
|
messageBox warningMessage title:«Warning« |
|
) |
|
) |
|
|
|
clearUndoBuffer() |
|
true |
|
), |
|
|
|
fn changeRendererToCorona =( |
|
if converterSettings.switchRenderEngine do ( |
|
if substring (classof renderers.current as string) 1 6 != «Corona« then ( |
|
renderers.current = CoronaRenderer() |
|
|
|
— renderers.medit represents a Material Editor’s renderer. |
|
if not renderers.medit_locked do ( |
|
renderers.medit = CoronaRenderer() |
|
) |
|
) |
|
) |
|
), |
|
|
|
— High-level Converter functionality |
|
fn convertSceneLights ErrorReport:true =( |
|
cntr = 0 |
|
|
|
allLights = for o in objects where superclassof o == light collect o |
|
|
|
for i in allLights do ( |
|
if isValidNode i do ( |
|
if i.parent != undefined and classof i.parent == DaylightAssemblyHead then ( |
|
) else ( |
|
local newLight = createCoronaLights i |
|
if newLight != #NoReplacement do ( |
|
replaceInstances i newLight |
|
) |
|
cntr += 1 |
|
) |
|
) |
|
) |
|
for o in (getclassinstances DaylightAssemblyHead) do ( |
|
cntr += 1 |
|
orig_light = o.sun |
|
cls = classof orig_light |
|
|
|
local new_light = case cls of ( |
|
VraySun: lightConvMethods.convertFrom_VraySun orig_light |
|
mr_Sun: lightConvMethods.convertFrom_mrSun orig_light |
|
IES_Sun: (CoronaSun()) |
|
Directionallight: (CoronaSun()) |
|
default: orig_light |
|
) |
|
o.sun = new_light |
|
|
|
if new_light != orig_light do ( |
|
delete new_light |
|
) |
|
o.sky = undefined |
|
) |
|
|
|
delete (for elem in converterTempData.new_lights where (superclassof elem == light) and isvalidnode elem collect elem) |
|
|
|
if converterSettings.printInfo do ( |
|
format «Attempted to convert % lights.nn« cntr |
|
) |
|
|
|
changeRendererToCorona() |
|
cleanConversionData() |
|
|
|
if ErrorReport do ( |
|
createErrorReports() |
|
) |
|
), |
|
|
|
fn convertSceneMtlsMaps ErrorReport:true =( |
|
— Material conversion |
|
cntr = 0 |
|
|
|
local problematicMtls = ProblematicMaterials() |
|
local supportedMtlClassNames = copy converterTempData.supportedMtlClassNames #noMap |
|
|
|
if matConvMethods.owner.converterSettings.ignoreLegacyMaterials == true do ( |
|
local idx = findItem supportedMtlClassNames «CoronaLegacyMtl« |
|
if idx != 0 do ( |
|
deleteItem supportedMtlClassNames idx |
|
) |
|
) |
|
for supportedMtlClassName in supportedMtlClassNames do ( — Where supportedMtlClassName.creatable. |
|
local mtlClass = execute supportedMtlClassName |
|
if classof mtlClass == material do ( |
|
local mtlClassInstances = getclassinstances mtlClass processAllAnimatables:false processChildren:false asTrackViewPick:false — HUGE SLOW DOWN!!!!!!!!!!!!! |
|
for mtlClassInstance in mtlClassInstances do ( |
|
replaceInstances mtlClassInstance (convertToNativeCoronaMtl mtlClassInstance &problematicMtls processMaps:fals) |
|
cntr += 1 |
|
) |
|
) |
|
) |
|
|
|
if converterSettings.printInfo then ( |
|
format «Successfully converted % / % materials.nn« converterTempData.newMaterials.count cntr |
|
) |
|
|
|
if converterSettings.showWarnings then ( |
|
printConversionWarnings problematicMtls |
|
) |
|
|
|
— Map conversion |
|
cntr = 0 |
|
|
|
for c in converterTempData.supportedMapClassNames do ( |
|
cls = execute c |
|
if classof cls == textureMap do ( |
|
classInst = getclassinstances cls processAllAnimatables:false processChildren:false asTrackViewPick:false — HUGE SLOW DOWN!!!!!!!!!!!!! |
|
for i in classInst do ( |
|
local newMap = convertToCoronaBitmap i |
|
if newMap != #NoReplacement then ( |
|
converterTools.replaceMapInstances i newMap |
|
) |
|
cntr += 1 |
|
) |
|
) |
|
) |
|
|
|
if converterSettings.printInfo do ( |
|
format «Successfully converted % / % maps.nn« converterTempData.newMaps.count cntr |
|
) |
|
|
|
changeRendererToCorona() |
|
cleanConversionData() |
|
|
|
if ErrorReport do ( |
|
createErrorReports() |
|
) |
|
), |
|
|
|
fn convertScene =( |
|
convertSceneMtlsMaps ErrorReport:false |
|
convertSceneLights ErrorReport:false |
|
createErrorReports() |
|
), |
|
|
|
fn convertNodeArray nodeArray ErrorReport:true =( |
|
cntr = 0 |
|
|
|
local problematicMtls = ProblematicMaterials() |
|
|
|
for obj in nodeArray do ( |
|
mat = obj.material |
|
if mat != undefined do ( |
|
replaceInstances mat (convertToNativeCoronaMtl mat &problematicMtls processTextureMaps:true) |
|
cntr += 1 |
|
) |
|
) |
|
|
|
if converterSettings.printInfo do ( |
|
format «Successfully converted % / % materials.nn« converterTempData.newMaterials.count cntr |
|
) |
|
|
|
if converterSettings.showWarnings then ( |
|
printConversionWarnings problematicMtls |
|
) |
|
|
|
changeRendererToCorona() |
|
cleanConversionData() |
|
|
|
if ErrorReport do ( |
|
createErrorReports() |
|
) |
|
), |
|
|
|
fn convertMaterialArray matArray ErrorReport:true =( |
|
cntr = 0 |
|
|
|
local problematicMtls = ProblematicMaterials() |
|
|
|
for mat in matArray do ( |
|
replaceInstances mat (convertToNativeCoronaMtl mat &problematicMtls processTextureMaps:true) |
|
cntr += 1 |
|
) |
|
|
|
if converterSettings.printInfo do ( |
|
format «Successfully converted % / % materials.nn« converterTempData.newMaterials.count cntr |
|
) |
|
|
|
if converterSettings.showWarnings then ( |
|
printConversionWarnings problematicMtls |
|
) |
|
|
|
changeRendererToCorona() |
|
cleanConversionData() |
|
|
|
if ErrorReport do ( |
|
createErrorReports() |
|
) |
|
), |
|
|
|
— Converter Dialog |
|
CoronaConverterRoll = rollout CoronaConverterRoll («Corona Converter « + converterTools.getVersion()) width:576 height:488 ( |
|
local owner = if owner != undefined do ( |
|
owner |
|
) |
|
|
|
local padding = 4 |
|
|
|
local groupbox_first_element_offset = [10, 20] |
|
local groupbox_element_height = 16 |
|
|
|
fn compute_groupbox_height row_count =( |
|
local TOLERANCE = 25 |
|
/*return*/ TOLERANCE + (groupbox_element_height + padding) * row_count |
|
) |
|
|
|
— Left column |
|
local left_column_width = 205 |
|
|
|
— General options groupbox |
|
local options_groupbox_top_left = [8, 8] |
|
local options_groupbox_height = compute_groupbox_height(7) |
|
groupBox grpOptions «General options« pos: options_groupbox_top_left width: left_column_width height: options_groupbox_height |
|
|
|
local current_element_top_left = options_groupbox_top_left + groupbox_first_element_offset |
|
local PREFIX_TOOLTIP = «Add a prefix to name of all converted materials.« |
|
checkbox addPrefixCheckbox « Add prefix to converted materials:« pos: current_element_top_left width:194 height: groupbox_element_height checked:owner.converterSettings.addCoronaPrefix tooltip:PREFIX_TOOLTIP |
|
local line_edit_offset = [10, 0] |
|
edittext prefixLineEdit «« pos: ((current_element_top_left += [0, groupbox_element_height + padding]) + line_edit_offset) width:150 height: groupbox_element_height tooltip:PREFIX_TOOLTIP |
|
checkbox mentalRayLightsToCoronaLightsCheckbox « mr Area Light(s) to CoronaLight(s)« pos: (current_element_top_left += [0, groupbox_element_height + padding]) width:185 height: groupbox_element_height checked:owner.converterSettings.miLightsToCrnLights tooltip:«Convert mr Area Omni Light(s) and mr Area Spot Light(s) to CoronaLight(s).« |
|
checkbox bitmapTextureToCoronaBitmapCheckbox « Bitmap(s) to CoronaBitmap(s)« pos: (current_element_top_left += [0, groupbox_element_height + padding]) width:168 height: groupbox_element_height checked:owner.converterSettings.bitmapTextureToCoronaBitmap tooltip:«Convert Bitmap texture maps to CoronaBitmap(s).« |
|
checkbox translucencyEnablesThinShellCheckbox « Enable «Thin shell« if translucent« pos: (current_element_top_left += [0, groupbox_element_height + padding]) width:194 height: groupbox_element_height checked:owner.converterSettings.translucencyEnablesThinShell tooltip:«Enable «Thin shell« parameter of the converted material, if the original material was translucent. Physically based materials in Corona Renderer are only allowed to use translucency effects when describing objects with «Thin shell«.« |
|
checkbox switchToCoronaRendererCheckbox « Switch to Corona Renderer« pos: (current_element_top_left += [0, groupbox_element_height + padding]) width:188 height: groupbox_element_height checked:owner.converterSettings.switchRenderEngine tooltip:«Switch active renderer of the current scene to Corona Renderer.« |
|
checkbox ignoreLegacyMaterialsCheckbox « Ignore legacy materials« pos: (current_element_top_left += [0, groupbox_element_height + padding]) width:188 height: groupbox_element_height checked:owner.converterSettings.ignoreLegacyMaterials tooltip:«Do not convert CoronaLegacyMtl to CoronaPhysicalMtl.« |
|
|
|
|
|
— V-Ray specific options groupbox |
|
local vray_groupbox_top_left = options_groupbox_top_left + [0, options_groupbox_height + padding] |
|
local vray_groupbox_height = compute_groupbox_height(5) |
|
groupBox grpVray «V-Ray specific options« pos: vray_groupbox_top_left width: left_column_width height: vray_groupbox_height |
|
|
|
local current_element_top_left = vray_groupbox_top_left + groupbox_first_element_offset |
|
local TEXT_OFFSET = 6 |
|
label lblVRayConversionInformation1 «Note: V-Ray specific objects, lights and« pos: (current_element_top_left + [0, TEXT_OFFSET / 2]) |
|
label lblVRayConversionInformation2 «materials are supported only if V-Ray« pos: (current_element_top_left += [0, groupbox_element_height + padding]) |
|
label lblVRayConversionInformation3 «renderer is installed in 3ds Max.« pos: (current_element_top_left += [0, groupbox_element_height + padding — TEXT_OFFSET / 2 ]) |
|
checkbox vrayHdriToBitmapCheckbox « Convert VRayHDRI(s)« pos: (current_element_top_left += [0, groupbox_element_height + padding + TEXT_OFFSET]) width: 168 height: groupbox_element_height checked:owner.converterSettings.VrayHDRIToBitmaptexture tooltip:«Convert VRayHDRI texture maps to standard Bitmap texture maps.« |
|
checkbox convertVrayProxiesCheckbox « Convert V-Ray proxies« pos: (current_element_top_left += [0, groupbox_element_height + padding]) width:176 checked:owner.converterSettings.convertVrayProxies tooltip:«Convert V-Ray proxies to Corona proxies. (Opens a pop-up dialog with further options during the conversion.)« |
|
|
|
— Conversion groupbox |
|
local conversion_groupbox_top_left = vray_groupbox_top_left + [0, vray_groupbox_height + padding] |
|
local button_height = 30 |
|
local button_with_padding_height = button_height + padding |
|
local conversion_groupbox_height = compute_groupbox_height(6) + button_with_padding_height |
|
groupBox grpConv «Conversion« pos: conversion_groupbox_top_left width: left_column_width height: conversion_groupbox_height |
|
|
|
local current_element_top_left = conversion_groupbox_top_left + groupbox_first_element_offset |
|
radiobuttons rdoMode «« pos: current_element_top_left width:82 height:80 offsets: #([0, padding * 0], [0, padding * 1], [0, padding * 2], [0, padding * 3], [0, padding * 4]) labels:#(«Everything (materials, maps, lights)«, «Scene materials and maps only«, «Scene lights only«, «Materials of selected objects only«, «Selected material editor slot only«) columns:1 tooltip:«Selection modes will convert materials and maps without breaking instancing, so be aware that other materials could be also affected.« |
|
local expected_conversion_radiobuttons_height = (groupbox_element_height + padding) * 5 |
|
checkbox showWarningsCheckbox « Show warnings« pos: (current_element_top_left += [0, expected_conversion_radiobuttons_height]) width:188 height: groupbox_element_height checked:owner.converterSettings.showWarnings tooltip:«Show conversion-related warnings.« |
|
button btnStartConverting «Convert« pos: (current_element_top_left += [0, groupbox_element_height + padding]) width: (left_column_width — groupbox_first_element_offset.x * 2) height: button_height |
|
|
|
— Right column |
|
local right_column_width = 350 |
|
|
|
— Individual tools groupbox |
|
local tools_groupbox_height = 200 |
|
local button_height = 20 |
|
local padding = 5 |
|
local tools_groupbox_top_left = options_groupbox_top_left + [left_column_width + padding, 0] |
|
groupBox grpTools «Individual tools« pos: tools_groupbox_top_left width: right_column_width height: tools_groupbox_height |
|
|
|
local current_element_top_left = tools_groupbox_top_left + groupbox_first_element_offset |
|
local resetCompactMaterialEditorButtonWidth = 215 |
|
button btnResetCompactMaterialEditor «Reset Compact Material Editor materials« pos: current_element_top_left width: resetCompactMaterialEditorButtonWidth height: button_height tooltip:«Reset all Compact Material Editor materials to default CoronaPhysicalMtl(s).« |
|
local show_statistics_button_width = right_column_width — resetCompactMaterialEditorButtonWidth — padding — groupbox_first_element_offset.x * 2 |
|
button btnStatistics «Show statistics« pos: (current_element_top_left + [resetCompactMaterialEditorButtonWidth + padding, 0]) width: show_statistics_button_width height: button_height tooltip:«Show statistics about CoronaPhysicalMtl(s) in the scene.« |
|
local disable_displacement_maps_button_width = resetCompactMaterialEditorButtonWidth |
|
button btnDisableDisplace «Disable displacement maps« pos: (current_element_top_left += [0, button_height + padding]) width: disable_displacement_maps_button_width height: button_height tooltip:«Disable displacement maps of all CoronaPhysicalMtl(s).« |
|
local convert_by_class_button_width = right_column_width — disable_displacement_maps_button_width — padding — groupbox_first_element_offset.x * 2 |
|
button btnConvertClass «Convert by class« pos: (current_element_top_left + [disable_displacement_maps_button_width + padding, 0]) width: convert_by_class_button_width height: button_height tooltip:«Convert specific unsupported material classes to default CoronaPhysicalMtl(s) (e.g. missing_mtl or Maxwell materials).« |
|
local CORRECTIVE_OFFSET = [5, 3] |
|
label lblShowMaps «Selected objects’ maps in viewport:« pos: ((current_element_top_left += [0, button_height + padding]) + CORRECTIVE_OFFSET) |
|
|
|
local showHideButtonWidth = 53 |
|
button btnShowMapsInViewport «Show« pos: (current_element_top_left + [right_column_width — groupbox_first_element_offset.x * 2 — showHideButtonWidth * 2 — padding, 0]) width: showHideButtonWidth height: button_height tooltip:«Workaround for displaying diffuse maps in the viewport — can be VERY SLOW!« |
|
button btnHideMapsInViewport «Hide« pos: (current_element_top_left + [right_column_width — groupbox_first_element_offset.x * 2 — showHideButtonWidth, 0]) width: showHideButtonWidth height: button_height tooltip:«Workaround for turning display of diffuse maps in the viewport off.« |
|
|
|
local disableCoronaRoundEdgesMapsLegacyModeButtonWidth = right_column_width — groupbox_first_element_offset.x * 2 |
|
button btnRndCrnsModeOff «Disable CoronaRoundEdges maps Legacy behavior« pos: (current_element_top_left += [0, button_height + padding]) width: disableCoronaRoundEdgesMapsLegacyModeButtonWidth height: button_height tooltip:«Disable «Legacy behavior« of all CoronaRoundEdges maps.« |
|
|
|
local fix_coronanormal_gamma_button_width = disableCoronaRoundEdgesMapsLegacyModeButtonWidth |
|
button btnFixCoronaNormalGamma «Fix CoronaNormal «Incorrect gamma« warnings« pos: (current_element_top_left += [0, button_height + padding]) width: fix_coronanormal_gamma_button_width height: button_height tooltip:«If some CoronaNormal node displays «Incorrect gamma« warning, try to fix it by switching its «Add gamma to input« option on or off. Only works if the input texture’s gamma is either 1.0 or 2.2.« |
|
local convert_vray_displacement_modifiers_button_width = disableCoronaRoundEdgesMapsLegacyModeButtonWidth |
|
button btnConvertVrayDisplacementMods «Convert VRayDisplacementMod(s) to CoronaDisplacementMod(s)« pos: (current_element_top_left += [0, button_height + padding]) width: convert_vray_displacement_modifiers_button_width height: button_height tooltip:«Convert VRayDisplacementMod modifiers to CoronaDisplacementMod modifiers.« |
|
local bitmap_to_coronabitmap_button_width = (right_column_width — groupbox_first_element_offset.x * 2) / 2 — padding / 2 |
|
button btnConvBitmapToCoronaBitmap «Bitmap(s) -> CoronaBitmap(s)« pos: (current_element_top_left += [0, button_height + padding]) width: bitmap_to_coronabitmap_button_width height: button_height tooltip:«Convert Bitmap texture maps to CoronaBitmap(s).« |
|
local coronabitmap_to_bitmap_button_width = right_column_width — bitmap_to_coronabitmap_button_width — padding — groupbox_first_element_offset.x * 2 |
|
button btnConvCoronaBitmapToBitmap «CoronaBitmap(s) -> Bitmap(s)« pos: (current_element_top_left + [bitmap_to_coronabitmap_button_width + padding, 0]) width: coronabitmap_to_bitmap_button_width height: button_height tooltip:«Convert CoronaBitmap(s) to Bitmap texture maps.« |
|
|
|
— Get help groupbox |
|
local help_groupbox_top_left = tools_groupbox_top_left + [0, tools_groupbox_height + padding] |
|
groupBox grpReaddMe «Get help« width: right_column_width height:65 pos: help_groupbox_top_left |
|
local current_element_top_left = help_groupbox_top_left + groupbox_first_element_offset |
|
hyperlink hlperfDebg «Performance debugging FAQ« address:«https://corona-renderer.com/link/4002« visitedColor:owner.converterSettings.UI_LINK_COLOR color:owner.converterSettings.UI_LINK_COLOR pos: current_element_top_left |
|
hyperlink hlAlbedo «Material albedo Helpdesk article« address:«https://corona-renderer.com/link/4000« visitedColor:owner.converterSettings.UI_LINK_COLOR color:owner.converterSettings.UI_LINK_COLOR pos: (current_element_top_left += [0, groupbox_element_height + padding]) |
|
|
|
— GUI handler |
|
on vrayHdriToBitmapCheckbox changed state do ( |
|
owner.converterSettings.VrayHDRIToBitmaptexture = state |
|
) |
|
|
|
on translucencyEnablesThinShellCheckbox changed state do ( |
|
owner.converterSettings.translucencyEnablesThinShell = state |
|
) |
|
|
|
on addPrefixCheckbox changed state do ( |
|
owner.converterSettings.addCoronaPrefix = state |
|
) |
|
|
|
on prefixLineEdit changed txt do ( |
|
owner.converterSettings.userPrefixStr = txt |
|
) |
|
|
|
on mentalRayLightsToCoronaLightsCheckbox changed state do ( |
|
owner.converterSettings.miLightsToCrnLights = state |
|
) |
|
|
|
on bitmapTextureToCoronaBitmapCheckbox changed state do ( |
|
owner.converterSettings.bitmapTextureToCoronaBitmap = state |
|
) |
|
|
|
on switchToCoronaRendererCheckbox changed state do ( |
|
owner.converterSettings.switchRenderEngine = state |
|
) |
|
|
|
on ignoreLegacyMaterialsCheckbox changed state do ( |
|
owner.converterSettings.ignoreLegacyMaterials = state |
|
) |
|
|
|
on showWarningsCheckbox changed state do ( |
|
owner.converterSettings.showWarnings = state |
|
) |
|
|
|
— Tools |
|
on btnResetCompactMaterialEditor pressed do ( |
|
owner.converterTools.resetCompactMaterialEditor() |
|
) |
|
|
|
on btnStatistics pressed do ( |
|
owner.converterTools.CoronaMtlStats() |
|
) |
|
|
|
on btnRndCrnsModeOff pressed do ( |
|
owner.converterTools.disableCoronaRoundEdgesMapsLegacyMode() |
|
) |
|
|
|
on btnShowMapsInViewport pressed do ( |
|
owner.converterTools.setMapsViewportVisibility true selected:true |
|
) |
|
|
|
on btnHideMapsInViewport pressed do ( |
|
owner.converterTools.setMapsViewportVisibility false selected:true |
|
) |
|
|
|
on btnDisableDisplace pressed do ( |
|
owner.converterTools.disableDisplacementMaps() |
|
) |
|
|
|
on btnConvertClass pressed do ( |
|
owner.converterTools.convertClass() |
|
) |
|
|
|
on btnFixCoronaNormalGamma pressed do ( |
|
owner.converterTools.fixCoronaNormalGamma() |
|
) |
|
|
|
on btnConvertVrayDisplacementMods pressed do ( |
|
convertAllVRayDisplacementModsToCoronaDisplacementMods() |
|
) |
|
|
|
on btnConvBitmapToCoronaBitmap pressed do ( |
|
owner.converterTools.convertBitmapToCoronaBitmap() |
|
) |
|
|
|
on btnConvCoronaBitmapToBitmap pressed do ( |
|
owner.converterTools.convertCoronaBitmapToBitmap() |
|
) |
|
|
|
— start conversion button |
|
on btnStartConverting pressed do ( |
|
max create mode |
|
with animate off ( |
|
case rdoMode.state of ( |
|
1: owner.convertScene() |
|
2: owner.convertSceneMtlsMaps() |
|
3: owner.convertSceneLights() |
|
4: owner.convertNodeArray (selection as array) |
|
5: owner.convertMaterialArray #(meditmaterials[activeMeditSlot]) |
|
) |
|
) |
|
|
|
if convertVrayProxiesCheckbox.checked and isVRayInstalled() then ( |
|
— If V-Ray is not installed, the VrayProxy class is not available in MAXScript. If we |
|
— used it anyway, MAXScript would encounter a runtime error. |
|
if (getClassInstances VrayProxy).count != 0 then ( |
|
CoronaProxyConverter.openGui() |
|
) |
|
) |
|
format «Conversion finished.nn« |
|
) |
|
|
|
on CoronaConverterRoll open do ( |
|
|
|
fn getIniSet sectionStr keyStr default =( |
|
out = (getinisetting owner.converterSettings.INI_PATH sectionStr keyStr) as string |
|
if out == «« then ( |
|
out = default as string |
|
) |
|
|
|
out |
|
) |
|
|
|
cc = owner.converterSettings |
|
|
|
vrayHdriToBitmapCheckbox.checked = cc.VrayHDRIToBitmaptexture = ((getIniSet «Vray« «VrayHDRI_Checked« cc.VrayHDRIToBitmaptexture) == «true«) |
|
|
|
prefixLineEdit.text = cc.userPrefixStr = (getIniSet «Options« «userString_String« cc.userPrefixStr) as string |
|
addPrefixCheckbox.checked = cc.addCoronaPrefix = ((getIniSet «Options« «userString_Checked« cc.addCoronaPrefix) == «true«) |
|
mentalRayLightsToCoronaLightsCheckbox.checked = cc.miLightsToCrnLights = ((getIniSet «Options« «MiLightsToCrn_Checked« cc.miLightsToCrnLights) == «true«) |
|
bitmapTextureToCoronaBitmapCheckbox.checked = cc.bitmapTextureToCoronaBitmap = ((getIniSet «Options« «BitmapToCrnBitmap_Checked« cc.bitmapTextureToCoronaBitmap) == «true«) |
|
convertVrayProxiesCheckbox.checked = cc.convertVrayProxies = ((getIniSet «Options« «ConvertProxies_Checked« cc.convertVrayProxies) == «true«) |
|
switchToCoronaRendererCheckbox.checked = cc.switchRenderEngine = ((getIniSet «Options« «SwitchEngine_Checked« cc.switchRenderEngine) == «true«) |
|
ignoreLegacyMaterialsCheckbox.checked = cc.ignoreLegacyMaterials = ((getIniSet «Options« «ignoreLegacyMaterials_Checked« cc.ignoreLegacyMaterials) == «true«) |
|
showWarningsCheckbox.checked = cc.showWarnings = ((getIniSet «Options« «ShowWarnings_Checked« cc.showWarnings) == «true«) |
|
|
|
cc.dialogPosX = (getIniSet «DialogPos« «pos_x« cc.dialogPosX) as float |
|
cc.dialogPosY = (getIniSet «DialogPos« «pos_y« cc.dialogPosY) as float |
|
if cc.dialogPosX != 0.0 and cc.dialogPosY != 0.0 then ( |
|
if (cc.dialogPosX > 0 and cc.dialogPosX < sysInfo.desktopSize.x — 200) do ( |
|
if (cc.dialogPosY > 0 and cc.dialogPosY < sysInfo.desktopSize.y — 100) do ( |
|
SetDialogPos CoronaConverterRoll [cc.dialogPosX, cc.dialogPosY] |
|
) |
|
) |
|
) |
|
|
|
if cc.EXPOSE_DEBUG_SETTINGS then ( |
|
CoronaConverterRoll.height += 60 |
|
) |
|
) |
|
|
|
on CoronaConverterRoll close do ( |
|
ini = owner.converterSettings.INI_PATH |
|
|
|
setINISetting ini «Vray« «VrayHDRI_Checked« (vrayHdriToBitmapCheckbox.checked as string) |
|
|
|
setINISetting ini «Options« «userString_String« prefixLineEdit.text |
|
setINISetting ini «Options« «userString_Checked« (addPrefixCheckbox.checked as string) |
|
setINISetting ini «Options« «MiLightsToCrn_Checked« (mentalRayLightsToCoronaLightsCheckbox.checked as string) |
|
setINISetting ini «Options« «BitmapToCrnBitmap_Checked« (bitmapTextureToCoronaBitmapCheckbox.checked as string) |
|
setINISetting ini «Options« «ConvertProxies_Checked« (convertVrayProxiesCheckbox.checked as string) |
|
setINISetting ini «Options« «SwitchEngine_Checked« (switchToCoronaRendererCheckbox.checked as string) |
|
setINISetting ini «Options« «ignoreLegacyMaterials_Checked« (ignoreLegacyMaterialsCheckbox.checked as string) |
|
setINISetting ini «Options« «ShowWarnings_Checked« (showWarningsCheckbox.checked as string) |
|
|
|
try ( |
|
setINISetting ini «DialogPos« «pos_x« ((GetDialogPos owner.CoronaConverterRoll).x as string) |
|
) catch () |
|
|
|
try ( |
|
setINISetting ini «DialogPos« «pos_y« ((GetDialogPos owner.CoronaConverterRoll).y as string) |
|
) catch () |
|
) |
|
), |
|
|
|
fn openGui =( |
|
createDialog CoronaConverterRoll style:#(#style_titlebar, #style_sysmenu, #style_minimizebox) |
|
), |
|
|
|
fn destroyGui =( |
|
try ( |
|
destroydialog CoronaConverterRoll |
|
) catch () |
|
|
|
try ( |
|
destroydialog CoronaMtlConvStatsRoll |
|
) catch () |
|
|
|
try ( |
|
destroydialog CoronaMtlConvClassRoll |
|
) catch () |
|
), |
|
|
|
on create do ( |
|
CoronaConverterRoll.owner = this |
|
try ( |
|
deleteItem selectionsets (selectionSets[«converted_AD_mtls«]) |
|
) catch () |
|
) |
|
) |
|
|
|
CoronaConverter = CoronaConverterStr() |
|
CoronaProxyConverter = CoronaProxyConverterStr() |
|
|
|
if CoronaConverterSuppressGui == false or CoronaConverterSuppressGui == undefined do ( |
|
try ( |
|
windows.sendMessage (windows.getChildHWND 0 («Corona Converter « + CoronaConverter.CoronaConverterVersion) parent:#max)[1] 0x0010 0 0 |
|
) catch () |
|
|
|
try ( |
|
windows.sendMessage (windows.getChildHWND 0 «Corona Mtl Statistics« parent:#max)[1] 0x0010 0 0 |
|
) catch () |
|
|
|
try ( |
|
windows.sendMessage (windows.getChildHWND 0 «Convert by class« parent:#max)[1] 0x0010 0 0 |
|
) catch () |
|
|
|
CoronaConverter.openGui() |
|
) |
|
) |