Start a new topic

C# or Python example of automating Material creation

So I'm trying to make the process of building a large world in Vortex more efficient. We have bottlenecks when it comes to importing all the terrain geometry and building materials that have many layers. It's actually pretty amazing that Vortex supports up to 16 layers in a material, each with its own set of UV mapping coordinates. We are taking full advantage of that for making terrain for a city-sized world that has a rural and urban component. To make it graphically efficient we make layers of tiled dirt, grass, rock, etc and use masks for each layer on a different UV channel to blend all of them together.


But often we have to fix UV coordinates and edit masks and reimport the geometry/maps. This becomes especially complex with roads, especially at the intersections where several pieces of geometry come together and the road lines make it obvious when there is the slightest misalignment.  (btw - it would be nice if there was a one-button solution to re-import a texture that has been updated).


So I'm looking at working with the Python and C# Vortex SDK and all the great examples you gave us, but there is one example I don't see and that's one around importing textures and creating Materials with some layers and masks. Is it possible you have an example of that? (Or any other ideas around automation for this part of the creation process).


Thanks!


So you understand what we are trying to accomplish. Here is an example of a material all set up with the layers:


image


And what it looks like (this is just for testing, not a real example)


image


So there are 4 layers (dirt, cracked dirt, grass, and ice (all on UV map channel 1). The base layer has no mask (dirt). The other 3 layers have masks (all on UV channel 0). This way we can do terrain, roads with markings, parking lots with numbered slots. The tiled textures get reused all over the world. The masks are custom painted for each piece of geometry. This gives us the variation we need without overloading the world with textures, and without sacrificing image quality, which is very important to us. So when viewed up close the resolution is sharp.


We just want to automate the material generation with all those layers. For example, I import a new piece of geometry into the world, I want to look at an XML or JSON text file with the material info (which we will generate somehow) and I want the script to check if a tiled texture already exists in the world and make a clone so we aren't duplicating textures, and I want to import each texture and build the layer stack with the associated masks.


All I need to get started is a basic example showing how the SDK can import a texture from a file, and how to instantiate a material and add a texture layer. I'm sure I can figure out the rest. :)

Hi Ben,

 

Glad to hear the Graphics Gallery's capabilities are proving useful to you! Small precision: it's actually 16 textures per material. They can each have their own layer, but the mask textures do count in the limit (there's a counter at the bottom of the Properties panel to help you keep track).

 

I'll punt the coding question to our developers, however I'm curious about your texture re-import comment.

 

To re-import we right-click on the texture object in the Explorer and then specify the location of the texture file. Do I understand correctly that you would like to be able to skip the latter (for example, if the updated texture kept the same file name/location)?

 

---

Marc-Alexandre Vézina

Product Manager, Vortex Studio

Hi Marc-Alexandre,


Yes, that's exactly what I meant. If we could update the texture in one click, it would not only save a lot of time but would reduce human error. It gets confusing and it's easy to pick the wrong file when you have a lot of layers. I understand Vortex may not keep track of where it loaded each texture but it would be awesome if it could do that.


And thanks for asking the developers about an example of importing textures and building materials.


Appreciate the help!

Just another thought on the texture reloading. We use 3ds Max and Substance in our pipeline and they both have this feature. Which is why we are used to it. Of course 3ds Max uses external textures anyway so it automatically updates, but they also include a button in case you need to force it:


image


Substance Painter would be a better example since they use internal textures like Vortex. But they also have a quick way to reload the texture in case you updated it. So it remembers where it got each texture. You can Reload, Show it in Explorer... 


image


It makes the process of updating source maps very painless. :)



1 person likes this

I was looking at the guides again and I saw this note. I'm not sure if it means we can't create graphics objects in script?

image


See the scene I've attached to the comment. It has an example of a simulation script importing a texture and assigning it to an albedo layer of a material when starting the simulation. 

The Simulation Script extension has 3 fields:
inputs.material (extension pointer): where to apply that change
inputs.path (string): the path of the image to import
parameters.persistChange (bool): whether to keep that change or not when stopping the simulation

def on_add_to_universe(self, universe):

    self.newTexture = VxSim.importTexture(self.inputs.path.value)

    self.getOwner().toObject().add(self.newTexture.getExtension())

    material = VxSim.GraphicsMaterialInterface(self.inputs.material.value)

    if (material is not None):

        if (len(material.mAlbedoLayers) < 1):

            material.mAlbedoLayers.add()

            layer = material.mAlbedoLayers[0]

            layer.mTexture.value = self.newTexture

    pass

def on_remove_from_universe(self, universe):

    if (self.parameters.persistChange.value is False):

        material = VxSim.GraphicsMaterialInterface(self.inputs.material.value)

        if (material is not None):

            material.mAlbedoLayers.resize(1)

            self.getOwner().toObject().remove(self.newTexture.getExtension())

            self.newTexture = None

    pass


2 people like this
Login to post a comment