Help tweaking rotation code.

Started by Sanma, January 11, 2019, 01:18:42 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Sanma

Solution in the fourth post.




Hello,

I've been trying to figure out how to create a script to process a lot of models, but my lack of knowledge in coding is making the process difficult. What I need the script to do is the following (there will be only one model in the scene each time):

Set Texture from Disk (always the same, using Texture Maps)
Render image, adding "A, B [...], or F" at the end, depending on the render iteration.
Rotate 60 degrees (Using Isometric, Orthographic camera)

The process repeats the rotation and rendering 6 times in total, and then I move on to the next model.

The problems I am facing:
1. I can't make the rotation work properly. I'm using the following code:

rot = luxmath.Matrix().makeIdentity().rotate(luxmath.Vector((0, -60, 0)))
tree = lux.getSceneTree()
model = tree.find(name="SM", types=(lux.NODE_TYPE_MODEL))
model[0].applyTransform(rot)


It does rotate, just not at all like when I rotate -60 ° on the Y axis using the move tool. (Translation seems to slightly change as well when I rotate with the move tool, image attached, and rotation using code seems to rotate much more than with the move tool as well.)

To render I'm using the following at the moment, which works fine:

lux.renderImage("C:/Users/Sanma/Desktop/Renders/" + model[0].getName() + ".png", width = 1024, height = 686)

Finally, I cannot figure out at all how to change the Texture. There seems to be a "setMaterial" function, but I'm not sure if that's the way to go or how to use it, considering I don't use a material from the library, but a texture map.

Letting the script import each model in a folder and run the code would also be a plus, but it's not completely necessary, as long as I can get some help with the above I'll be extremely grateful.

Thank you for the help!

Sanma

Update, this is the code I have so far:

def main(tileset="Grass")
    # First get the model sceneNode and ID, and apply the material. Only works having 1 model in the scene.
    tree = lux.getSceneTree()
    model = tree.find(name="SM", types=(lux.NODE_TYPE_MODEL))
    model_id = model[0].getID()
    lux.setObjectMaterial("TileTextures", model_id)

    # Render the original image.
    lux.renderImage("C:/Users/Sanma/Desktop/Hex/" + tileset + "/" + tileset + "_" + model[0].getName() + ".A.png", width=1024, height=686)

    for char in "BCDEF":

        # Rotation. Doesn't currently work.
        # rot = luxmath.Matrix().makeIdentity().rotate(luxmath.Vector((0, -60, 0)))
        # model[0].applyTransform(rot)

        # Render the image, adding .B, .C, etc.
        lux.renderImage("C:/Users/Sanma/Desktop/Hex/" + tileset + "/" + tileset + "_" + model[0].getName() + "." + str(char) + ".png", width = 1024, height = 686)

main()


I haven't tested most of the code yet, but in principle the only problem I'd have is the rotation that I can't get to work properly as explained in my previous post.
Ideally I'd be able to switch materials in the Multi-material I created, which I can't see how to do either, but I could do that manually. Rotation is really the big thing I can't solve here.

Thanks again!

RX7_Mark

Hi,

I need some help with how you are doing this part:

"Render image, adding "A, B [...], or F" at the end, depending on the render iteration."

What is the most basic way to do this? I know very little Python.

If my model name is changing all the time, but I want my script to just get the current name and add a "1" or "A" to the end and render 1 images from 3 different camera views.

To help with your rotating problem... This might not be the easiest way to do it, but it should work from what I just tried.

Create a camera view called "Cam0" (or whatever you want) and have it as the 0 degree starting point. Then rotate 60 degrees and make a new camera called "Cam60"... "Cam120"... eventually "Cam360"

Then use:

lux.setCamera("Cam0")

and whatever render options you use

opts = lux.getRenderOptions()
opts.setMaxTimeRendering(10)
lux.renderImage("C:/Users/Public/Documents/KeyShot 8/......)

Then the next line is:

lux.setCamera("Cam60")
opts = lux.getRenderOptions()
opts.setMaxTimeRendering(10)
lux.renderImage("C:/Users/Public/Documents/KeyShot 8/......)

lux.setCamera("Cam120")
opts = lux.getRenderOptions()
opts.setMaxTimeRendering(10)
lux.renderImage("C:/Users/Public/Documents/KeyShot 8/......)

Etc....

It might be initially tedious, but I don't see why it wouldn't work... I just need help with the file names now  ;D



Sanma

Hi Mark,

I have actually "completed" (still fine tuning) the script already. You can see below a simple example on how to iterate as well using a for loop; basically for each character in "ABCDEF" (6 times), it will render an image and add the character it is currently sitting on to the filename (you can see "char" twice below).


for char in "ABCDEF":
    lux.renderImage("C:/Export/Location/" + filename +  "_" + str(char) + ".png")


Currently the entire code does the following:

1. Create a list of all files in a directory.
2. Import the first file.
3. Apply a Material.
4. Render and Rotate 6 times.
5. Repeat steps 3 and 4 until all materials have been applied.
6. Hide the model (since I couldn't figure out how to delete it from the scene)
7. Keep importing, rendering, rotating, texturing the rest of the files until the list is empty.

# AUTHOR Nick S.
# VERSION 0.2
# Imports all files in a folder, Renders and Rotates 6 times with 6 tilesets.

import os


def main():

    tiles_list = ["Grass", "Green", "Snow", "Desert", "Waste", "Alien"]

    # Make a list with the names of every file in a folder.
    file_list = os.listdir("C:/Users/Nick/Desktop/ISO/Hex_Ground")
    list_size = len(file_list)

    # for each file
    for i in range(0, list_size):

        # Import file
        file_current = file_list.pop(0)
        file_name, file_ext = os.path.splitext(file_current)

        lux.importFile(path="C:/Users/Nick/Desktop/ISO/testimport/" + file_current)

        # Get SceneNode (model) and ID.
        tree = lux.getSceneTree()
        model = tree.find(name=file_name, types=(lux.NODE_TYPE_OBJECT))
        model_id = model[0].getID()

        # for each tileset, set the texture.
        for tileset in tiles_list[:len(tiles_list)]:

            lux.setObjectMaterial("TileTextures" + tileset, model_id)

            for char in "ABCDEF":

                # Render the image, adding .A, .B, .C, etc.
                lux.renderImage("C:/Users/Nick/Desktop/ISO/Hex_Ground/Renders/Automated/" + tileset + "/" + tileset
                                + "_" + file_name + "." + str(char) + ".png", width=1024, height=686)

                # Rotation.
                rot = luxmath.Matrix().makeIdentity().rotateAroundAxis(luxmath.Vector((0, -1, 0)), 60)
                model[0].applyTransform(rot)

        model[0].hide()


# Run the code once.
main()



If anyone knows how to delete a model, please let me know. At the moment I'm just hiding them from view.

Cheers,
Nick.