[Closed] Texturing by normals
Hello,
I’ve been working on a texturing/mapping method which main purpose is to sort of expand the Top/Bottom material to a Top/Bottom/Left/Right/Front/Back material.
I found a lot of help on another thread. There Bobo wrote a function I needed to start working that goes like this:
[left]([/left]
theMesh = snapshotasmesh $ –get the TriMesh into memory
vchannel = 0 –define vcolor channel index
vert = 1 –this is the vertex to which I want to calculate a new colour
[left]– Nn contains the normal of this vector[/left]
– Get all faces using the vert as array
[left]– Actually I don’t need to go through the whole of this loop,[/left]
[left]– to get on correct mV is enough.[/left]
fArray = (meshop.getFacesUsingVert theMesh vert) as array
for f in fArray do – for each face,
(
–Get geometry face – vertex is either its first, second or third
[left]component [/left]
gF = getFace theMesh f
– Get map face (index corresponds with geometry face)
mF = meshop.getMapFace theMesh vchannel f
– Find order inside the mesh face – vertex (component) order will be the
[left]same in both[/left]
mV = case of
(
(gF.x == vert): mF.x
(gF.y == vert): mF.y
(gF.z == vert): mF.z
)
–apply the calculated colour to the vertex
[left]meshop.setMapVert theMesh vchannel mV (myFunction Nn blend_amnt)[/left]
)–end f loop
delete theMesh –release the mesh from memory
[left])–end script[/left]
After making this function go through a loop for every vertex of the mesh, I got this (each sphere corresponds to a different amount of blend_amnt):
But now I need to do more:
|———————————-o———————————-|
1.- This only works for plain colours. In the body of myFunction I specify a point3 colour and that’s it, no more. How do I make it work for materials?
– these are the colours for each side of the object
sideX = [1,0,0]
sideNegX = [0,1,1]
sideY = [0,1,0]
sideNegY = [1,0,1]
sideZ = [0,0,1]
sideNegZ = [1,1,0]
– ensure that sum of all mask is = 1
maskSum = maskXCombined + maskNegXCombined + maskYCombined + maskNegYCombined + maskZCombined + maskNegZCombined
maskXCombined = maskXCombined / maskSum
maskNegXCombined = maskNegXCombined / maskSum
maskYCombined = maskYCombined / maskSum
maskNegYCombined = maskNegYCombined / maskSum
maskZCombined = maskZCombined / maskSum
maskNegZCombined = maskNegZCombined / maskSum
– this is the resulting colour to be applied to the vertex.
sideXmaskXCombined + sideNegXmaskNegXCombined + sideYmaskYCombined + sideNegYmaskNegYCombined + sideZmaskZCombined + sideNegZmaskNegZCombined
So if this is how I apply colour, how do I apply a material or procedural texture?
|———————————-o———————————-|
2.- This is done by going through a vertex loop. Is there anyway to do this by pixel?
Thank you for your help.
- For materials you’ll be looking at material IDs. Material IDs are specified per-face (no blending there)… getting a face’s normal is a single call so setting that up to get a cube-aligned material ID assignment should be easy enough.
2a. Only if you wrote your own plugin. Materials/maps are evaluated per pixel at rendertime, while your script runs well outside of the renderer.
2b. Although you could probably get a similar blending by using a Blend or MultiBlend/Composite material/map, and using Falloff maps set to the various axes to mask the materials/maps.
Hello ZeBoxx,
Thank you for your answer.
What do you mean when you say “no blending there”?
I suppose this means that I cannot assign mat1 and mat2 to the same face and expect them to be automatically blended, right? But what if I get <u,v,w> from mat1, <u,v,w> from mat2 and use those values to get the resulting material for that face. Can I do that and apply to the final line of code of my function?
sideXmaskXCombined + sideNegXmaskNegXCombined + sideYmaskYCombined + sideNegYmaskNegYCombined + sideZmaskZCombined + sideNegZmaskNegZCombined
[font=Arial]
???
Thank you.
[/font]
Correct. The face would have to use a single material – for example a Blend or Composite material – and use a map/multiple maps to blend between the two. You’ve already got the last part ‘done’, so shouldn’t be too much of a stretch. Still not as simple as being able to assign materials to vertices and get automatic blending, though
Hello,
When I execute the setFaceMatID function, why can’t I see the results on the viewport or when I render?
Supposing I have three materials defined, and mesh selected, if I execute
setFaceMatID $ 1 3
3
update $
OK
getFaceMatID $ 1
3
[font=Arial]It all looks fine on the listener, but I can’t see face 1 with the material applied.
Thank you.
[/font]
Make sure that those three materials are part of a Multi/Sub-Object material that is actually applied to the object. If that is already the case, make sure you’re looking at Face 1 in the viewport – I just ran it on an object of mine and had to look around a bit to find Face 1… was easy to miss as it was rather small. Might be better to test on a simple Box object first
Hello ZeBoxx2,
Thank you for your answer. Actually I didn’t know about the Multi/Sub-Object material part. So as soon as I did that, everything went ok.
Now on to something else.
If you could please check the first of these post, the one I opened this thread with, you will notice six variables:
– these are the colours for each side of the object
sideX = [1,0,0]
sideNegX = [0,1,1]
sideY = [0,1,0]
sideNegY = [1,0,1]
sideZ = [0,0,1]
sideNegZ = [1,1,0]
[font=Arial]According to the author of that code:[/font]
[color=navy][font=Arial]The variables sideX, sideNegX, sideY etc. that I use to store simple color values should in your case store the resulting color/opacity (after all the lighting etc.) of the 6 submaterials the user did set up.[/color][/font]
So, how can get that [color=navy][font=Arial]resulting color/opacity (after all the lighting etc.)? The one who gave me that code doesn’t work with MAXScript, and I don’t know where else to look.
Thanks again
[/color][/font]
Hello everyone,
Can someone please post a code example that uses the blend constructor?
Let’s suppose I have a given face and two materials. I would like to apply to that face a blending of 20% of the first material, and 80% of the other one. How do I do this?
Any help would be much appreciated.
Ok… let me try to revive this post!
I once asked if it was possible to assign a material to an object, and change a given propperty of that material for each face. The answer I recieved was a plain NO.
Now I ask: is it possible to dinamically create (using MAXScript) a new material and assign it to each face?
That’s what I want to do. I created a Multi/Sub-Object material. Now I want, for each face, create a blending of two or three materials with a specific mixing amount.
Sorry about that… missed that post.
Uhm… I think that bit is referring to vertex colors / vertex illumination values? Whole ‘nother topic…
In terms of blending them the way you desired – indeed, no, not with any standard functionality.
Yes, quite simply so.
And that’s where things get more complex than ‘yes, quite simply so’ again.
A face can only have 1 material. That material itself can be a blending material – such as a Blend material, blending between 2 materials – but still only 1 material. So you can’t set, directly, per face, that you want it to have 20% of Material A and 80% of Material B and call it a day.
You would – just for an example – give that face a Material ID of 1. That corresponds to the 1st material slot in a Multi-/Sub-object material. That 1st material slot, then, would have a Blend material, which would have Material A and Material B, and the appropriate blending amount.
Now let’s say you need to have 21% of Material A and 79% of Material B on another face. As mentioned, the face itself can’t dictate the amount of blending, so you would have to set it up with Material ID 2, the 2nd multisub material slot, and have another blend. And so forth and so on.
Now, if the number of materials you have to blend between – e.g. always just 2 or 3 at a time, then you -can- use vertex colors to se the amount of blending between two materials without having to set up a ton of different Blend materials. Just a single Blend material between 2 materials would be needed, while using a Vertex Color map to drive the blend amount between those two materials. The Vertex Color map can take its values from the vertex colors on the object. You’ll still need a different Material ID and thus Blend material for any combination of 2 (or more) materials that you’d want to blend on any given face, though.
Scripting this is a world of hurt
Perhaps that’s not the easiest way to go, anyway, though… what is it for, exactly?
Can you see the images attached to the first post of this thread? Those images are made up of standard colours. I simply assign red or blue or whatever and make a simple calculation.
Now I have to go a bit further and do that with textures and materials. And to do so I need to blend.
I think my approach can work if I create a material for each face, but I can’t try it because I don’t know how to create a material dinamically… There is, for instance, a Blend() constructor, but I don’t understand how to use it.
alright, we can take this from the top a bit and see where we end up
Keep in mind that the blue text below is output from the MaxScript listener – it’s not code you actually enter.
-- create a red material
materialA = standardMaterial diffuse:(color 255 0 0)
Standardmaterial:Standard
-- create a blue material
materialB = standardMaterial diffuse:(color 0 0 255)
Standardmaterial:Standard
-- place both in the mateial editor
meditMaterials[1] = materialA
Standardmaterial:Standard
meditMaterials[2] = materialB
Standardmaterial:Standard
-- create a new Blend material
materialAB = Blend()
Blend:Blend
-- bit rusty on my Blend materials, let's see what its parameters are
showproperties materialAB
.mixAmount : percent
.lower : float
.upper : float
.useCurve : boolean
.interactive : integer
.map1 (Map_1) : material
.map2 (Map_2) : material
.mask : texturemap
.map1Enabled (Map_1_Enable) : boolean
.map2Enabled (Map_2_Enable) : boolean
.maskEnabled (MaskEnable) : boolean
false
-- ah, yes
-- Assign the red and blue materials to the Blend material
materialAB.map1 = materialA
01 - Default:Standard
materialAB.map2 = materialB
02 - Default:Standard
-- Blend the two at 50%
materialAB.mixAmount = 50
50
-- and drop it in the material editor as well
meditmaterials[3] = materialAB
Blend:Blend
Now for a multi/sub-object material and assigning a material to one of its IDs…
-- create a new multi/sub-object material
multisub = Multimaterial()
#Multi/Sub-Object:Multimaterial(Standard:Material #49, Standard:Material #50, Standard:Material #51, Standard:Material #52, Standard:Material #53, Standard:Material #54, Standard:Material #55, Standard:Material #56, Standard:Material #57, Standard:Material #58)
-- what were its parameters, again...
showproperties multisub
.materialList (Material) : material array
.mapEnabled (Map_1_Enable) : boolean array
.names (Map) : string array
.materialIDList (Index) : int array
.material1 (alias for materialList[0])
false
-- materialList looks interesting...
multisub.materialList
#(Material #49:Standard, Material #50:Standard, Material #51:Standard, Material #52:Standard, Material #53:Standard, Material #54:Standard, Material #55:Standard, Material #56:Standard, Material #57:Standard, Material #58:Standard)
-- looks like the list of materials (imagine that)
-- assign our AB blend material to the 2nd multi-/sub-object material slot
multisub.materialList[2] = materialAB
Blend:Blend
-- drop it in the material editor
meditmaterials[4] = multisub
#Multi/Sub-Object:Multimaterial(Standard:Material #49, Blend:Blend, Standard:Material #51, Standard:Material #52, Standard:Material #53, Standard:Material #54, Standard:Material #55, Standard:Material #56, Standard:Material #57, Standard:Material #58)
Now for changing the material ID of a selected Editable Poly (could be editable mesh, could even work with some mesh select bits, but let’s start with this one)…
-- create a plane with 4x4 segments
myPlane = plane lengthsegs:4 widthsegs:4
$Plane:Plane01 @ [0.000000,0.000000,0.000000]
-- convert it to an editable poly
convertToPoly myPlane
$Editable_Poly:Plane01 @ [0.000000,0.000000,0.000000]
-- assign our multi-/sub-object material to it
myPlane.material = multisub
#Multi/Sub-Object:Multimaterial(Standard:Material #49, Blend:Blend, Standard:Material #51, Standard:Material #52, Standard:Material #53, Standard:Material #54, Standard:Material #55, Standard:Material #56, Standard:Material #57, Standard:Material #58)
-- now let's change some of the polies' material IDs to 2 to bring up our Blend materia
polyOp.setFaceMatID myPlane 6 2
OK
polyOp.setFaceMatID myPlane 11 2
OK
-- force an update so that the material shows - redrawing the viewport would do as well
update myPlane
OK
I don’t speak dutch but, according to a translator, what I want to say is:
Hartelijk dank!!
And of course…
Thank you very much indeed. I’ll keep you posted to see if I finally get what I want.