Announcement

Collapse
No announcement yet.

Advanced V-Ray Python Scripting Questions

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Advanced V-Ray Python Scripting Questions

    I've been meaning to ask some of these questions for quite some time. I rely heavily on scripted Rhino and V-Ray to automate as much as possible. A few things I've never been able to figure out are:
    1. How to change the GPU devices programmatically via Python in Rhino and V-Ray. In the system service I wrote in Powershell that batch renders vrscenes for us automatically when they appear in a monitored folder, I had no issue selecting the GPU device by simply adjusting the environment variable
      Code:
      $env:VRAY_GPU_PLATFORMS = $DEVICE_MAP[$device]
      before vray.exe is invoked. In Rhino Python, I've tried editing the environment variables as well but nothing changes in the Asset Editor. I haven't gone as far as trying to change the default renderer back to Rhino and then back again to V-Ray but I have tried
      Code:
      vray.RefreshUI()
      of course and that didn't work.

      Any ideas? Here's what I tried when I last attempted to figure this out a while ago:
      Code:
      	   print(os.environ['VRAY_GPU_PLATFORMS'])
      	   os.environ['VRAY_GPU_PLATFORMS'] = "nvidia cuda nvidia geforce rtx 3080 ti gpu index0;nvidia cuda nvidia geforce rtx 3080 ti gpu index1;"
      	   print(os.environ['VRAY_GPU_PLATFORMS'])
      	   vray.RefreshUI()​
    2. Is it possible to adjust the rendering quality slider in the asset editor via Python so that I can render lower quality preview renders and switch to high quality production renders without having to manually intervene. I know I could save a low quality version of the VROPTS and a separate high quality one but what I REALLY want to know how to do is adjust the quality on-demand via Python.

      When I adjust the SettingsOptions quality_preset parameter, the quality slider in the Asset Editor changes but none of the other things like Noise Limit, Max Subdivs, etc actually change. I know that there are sometimes other related parameters that have to be adjusted for a change to take effect but I can't find anything else that's obvious between the vrscene and vropt files I've inspected. What am I missing?
      Code:
      vray2.Scene.Plugin('SettingsOptions').Param('quali ty_preset').Value = 2
      	vray.RefreshUI()​
    3. Is there an easier way to calculate the transforms for rotating bitmaps programmatically in V-Ray? I resorted to building my own lookup dictionary after going through rotations at 5 degree intervals because I otherwise had no idea how to come up with the numbers I would need to pass in order to rotate a bitmap 30 degrees horizontally and 15 degrees vertically for example. Here's a small chunk of my manually compiled lookup table looks like:
      Code:
      	TRANSFORMS = {
      	  'H000V000': (1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0),
      	
      	  'H-010V000': (0.984808, 0.173648, 0.0, -0.173648, 0.984808, 0.0, 0.0, 0.0, 1.0),
      	  'H-015V000': (0.965926, 0.258819, 0.0, -0.258819, 0.965926, 0.0, 0.0, 0.0, 1.0),
      	  'H-020V000': (0.939693, 0.34202, 0.0, -0.34202, 0.939693, 0.0, 0.0, 0.0, 1.0),
      	  'H-030V000': (0.866025, 0.5, 0.0, -0.5, 0.866025, 0.0, 0.0, 0.0, 1.0),
      	  'H-040V000': (0.766044, 0.642788, 0.0, -0.642788, 0.766044, 0.0, 0.0, 0.0, 1.0),
      	  'H-045V000': (0.707107, 0.707107, 0.0, -0.707107, 0.707107, 0.0, 0.0, 0.0, 1.0),
      	  'H-050V000': (0.642788, 0.766044, 0.0, -0.766044, 0.642788, 0.0, 0.0, 0.0, 1.0),​
      	   ...
      	}
      I compiled this lookup table manually but I'd love to get rid of it if there's a way to generate those matrix transformations using a formula or 3rd party library that can help.

  • #2
    Very interesting questions. I'll answer them all and will try to explain the reasons

    1) Changing env. variables from inside Rhino will not change them for V-Ray
    The reason is a bit lengthy, but stay with me.
    The env. variables were invented some 60 years ago for the UNIX operating system and they didn't change since. To me these are very stupid way to commutate data, and were basically invented to cut manual typing cmd. line arguments every time. Programmers were (and still are) lazy.
    On every modern OS the environment is LOCAL to each process. When you start your application the system copies the environment from the parent process (or the system process) and packs that copy with the new process. If you change a variable from one process, no other process will "see" the change in its environment. This goes even deeper - for C/C++ shared libraries (.dll) the environment is LOCAL to each individual library and in Rhino you have hundreds of .dlls loaded. Basically you're changing a variable in MyPlugin.rhp and that change is retained only for that .dll. Even RhinoPython will not see it, although it runs under the same process, but in a different .dll. The reason for that is CRT (C Runtime Library). Every C/C++ DLL initializes the CRT before it starts. That happens on system level. In windows the DLLs are actually hacked .EXEs, so there is no much of a difference whether you load a .dll or start an .exe. In both cases the process inherits an environment and makes a copy of it for itself.
    However there is a lucky exception. despite having getenv() and putenv() functions in CRT, Windows API provides GetEnvironmentVariable() and SetEnvironmentVariable(). Those work on a process level, not on an instance (dll level). Fortunately RhinoPython is IronPython which is .NET.
    The .NET interoperability with the environment goes thru the Windows one, hence it works on process level. The point is that you change some env. var in RhinoPython and that is visible to all .dlls loaded by Rhino. Potentially... unless the developers of the respective modules use getenv()/putenv() (CRT ones), insread of Windows API ones.

    So...
    VRayForRhino.rhp uses the Windows ones, but VRaySDKLibrary.dll uses the CRT ones. The Asset Editor cannot acquire the device list on its own (because JavaScript is too dump). So it asks V-Ray thru VRayForRhino.rhp and then VRaySDKLibrary.dll. As you remember that module can potentially see your change, but it does not uses the Windows API to retrieve the variables - it uses CRT, and hence your modification cannot reach it.

    VRaySDKLibrary.dll is loaded once at startup. You see "Loading V-Ray for Rhino" in the splash screen, right ? Well that is the place when the environment is copied from Rhino.exe and stored to VRaySDKLibrary.dll. No more changes, outside the .dll are visible to the .dll

    By their nature, env. vars are used to override certain behavior. Most usually some initialization conditions, like LD_LIBRARY_PATH on Unix-like OSs, That is why you run .sh files instead of .bin for the most part.
    If you want your changes to be visible to V-Ray, you have to make them before V-Ray is loaded.

    One more thing. Changing the current renderer does not unload V-Ray. It only changes which module responds to the Render command. V-Ray DLLs stay loaded for the lifetime of the Rhino instance.
    There are some voices that this could be changed and we load V-Ray DLLs on demand, but no concrete steps are made yet. I'm not sure if they will be.

    The easiest way for me to resolve your situation is to expose 2 methods to the COM interface, so you can call them from Python. Basically anything else is futile endeavor.
    I'll make a ticket for that

    2) The rendering quality slider is NOT a business logic. It is a UI script.

    There is no way to change it because there is no API for it. What gets changed is known only to NeUI, and that change from version to version. However there is a solution to that. The quality slider only makes immediate changes to a fixed set of parameters. You can detect the changes by exporting a .vropt file for every slider stop, and make a diff. You will quickly build up your lookup table. To give you a head start I'm attaching an extract from VfGH code, where the "logic" is just copied. It is several versions old, but for the most part will do.

    I'll talk to the UI team on how to expose that

    3) Yes, that is called 2D rotation matrix. You can find millions of online resources on that topic. The transformation is simple trigonometry. However you need to consider the folling:
    - V-Ray matrices are major-column (as oppose to Rhino)
    - I assume you're asking about rotation around the Z axis, that is usually related to 2D textures
    - You say "transformation", but your look up table only contains the rotation matrix. You need one more vector for the offset if you're going to set that to a transformation parameter.

    so.. let say 39 deg CCW . That is 39 * pi / 180 = 0.68067 rad

    RotZ = [ [cos, sin, 0] [-sin, cos, 0] [0, 0, 1]]
    RotZ = [ 0.7771, 0.6293, 0, -0.6293, 0.7771, 0, 0, 0, 1]

    There is a Rhino API call you can do from RhinoPython.
    For example for your look up table above, for angle -10, I call this:
    Code:
    import Rhino
    
    zangle = -10
    m = Rhino.Geometry.Transform.RotationZYX(Rhino.RhinoMath.ToRadians(zangle), 0, 0).Transpose() # V-Ray is column-major, Rhino is row-major. We need to transpose the matrix
    vm = (m.M00, m.M10, m.M20,  m.M01, m.M11, m.M21,  m.M02, m.M12, m.M22) # take only the matrix members
    
    print(vm)​
    The printout is
    Code:
    (0.98480775301220802, 0.17364817766693033, 0.0, -0.17364817766693033, 0.98480775301220802, 0.0, 0.0, 0.0, 1.0)
    that matches the entry in your LUT

    If you need a 3D transformation, you just fill in more values to Rhino.Geometry.Transform.RotationZYX() or Rhino.Geometry.Transform.RotationZYZ() respectively
    Attached Files
    Last edited by nikolay.bakalov; 24-03-2023, 08:44 AM.

    Comment


    • #3
      nikolay.bakalov I greatly appreciate the detailed technical responses!

      1) It'd be totally awesome to have some newly exposed methods for dynamically changing the render devices with V-Ray directly! As an extra bonus, having the ability to also check the current load of devices could come in handy. That could easily be done via Python independently of V-Ray probably but just throwing the idea out there. I'm looking forward to hopefully seeing support for setting the render devices in a future update. I did pretty quickly realize that the modifications of the environment variables I was making in Rhino Python were getting stuck in their own copy and weren't accessible to V-Ray it has been loaded. That's ultimately why my last resort was to try unloading and reloading V-Ray, of course, to no avail.... but I always could script the loading and unloading of Rhino itself so technically any environment variable updates that were made in between Rhino sessions would make their way to Rhino and then V-Ray

      2) A while back I did actually begin going down the path of diff-ing the .vropt files for the different quality settings but I never completed the work of putting my own lookup table together. The changes I was tracking were getting rather lengthy and seemed messy. I think I remember a few tests I did with changing all the related things that happen behind the scenes with the quality slider ended up causing some really weird behavior with V-Ray until it was closed and re-opened. I would have kept working through that if this were super importing but I decided to table the work and hope for a more official mechanism.

      Thanks for the attached sample. I was certainly on the right track when I first attempted this the manual way because the method I had started looks almost identical to what you shared! Of course V-Ray ended up in a weird and confused state on me as I was trying out these series of adjustments. I had to close and re-open Rhino and V-Ray completely in between attempts. I don't remember exactly what happened because it was quite a while ago and with an older version of V-Ray. I'll give this manual approach another shot but a formally exposed method for this would make a lot of sense alongside methods to adjust the devices.

      3) The vast majority of programmatic bitmap rotations I make are for bitmaps that are environment maps so they are set as Type: Environment in the Asset Editor versus a 2D Texture that would be created when used for a material. When we are first building out a rendering studio for a client, we sometimes produce what we call a Light Study. We have scripts that can either loop through a filesystem folder of environment maps or through pre-created Globalized asset editor environment map options to update the studio's primary reflection environment light (GI or V-Ray Dome) to point to each option and render low resolution product shot in every set camera angle and use a list of defined rotations for each environment map.. For jewelry, this somewhat brute force approach really helps narrow down the right environment map and rotations for each unique camera angle and product type for customers.

      So... I don't really need to make super intricate or advanced rotations. I'm not sure I'll need to adjust the offset. Each additional adjustments introduces many more potential options for a light study. We try to stick to only incremental rotations that are meaningful enough to produce a unique option while not going way overboard and flooding clients. I currently only have either just horizontal or vertical rotations mapped in my lookup table so I can only rotate each one alone but not together. Using a library to would help calculate the rotation matrix values properly would allow me to introduce some options potentially that that rotate the environments both horizontally and vertically in increments at the same time.

      I'll play around Rhino.Geometry.Transform.RotationZYX! Thanks for pointing me in the right direction!

      Comment


      • #4
        nikolay.bakalov just got around to updating V-Ray last week and noticed the "RhinoScriptComputeDeviceInfo" interface in the changelog. Super excited that made it in and just wanted to thank you for pushing that through. I already gave it a try and it works like a charm!

        Perhaps the next scripting win could include the quality presets eh?
        I've never had success with hacking all the modifications at once together

        Comment


        • #5
          hi,

          yes the quality preset is next. however that required some more messy change, since that code is in the AssetEditor, and I want to make it properly, which requires allocating resources from the UI team.
          will take some time

          Comment


          • #6
            Originally posted by nikolay.bakalov View Post
            hi,
            yes the quality preset is next. however that required some more messy change, since that code is in the AssetEditor, and I want to make it properly, which requires allocating resources from the UI team.
            will take some time
            Gotcha I didn't really consider the UI component but after thinking about it, I can see how the more hidden parameters being adjusted programmatically could require displaying what the user does see in the UI in a manner that they wouldn't normally be able to achieve if they were adjusting certain controls by hand. Am I on the right track there? Just trying to remember all those adjusted parameters from both your quality zip attachment and the very similar one I had put together basically by DIFFing scene files that were totally identical except for the quality slider being adjusted.

            If you're gonna be talking to the UI team, can I throw in just one UI thing only because I actually brought it up I think back during the beta of VR4 or VR5 and a handful of other more advanced users jumped in and threw in their votes. We even had one of the awesome Chaos team members acknowledge that it likely would be a trivial feature to drop in so they were gonna see about including it in the final release. Unfortunately it hasn't happened yet and I'm reminded of it every single time I work in the UI. The request was to have a simple toggle / boolean / checkbox next to the other global scene Configurations that allows us to set the default state of all panels and sub-panels to either expanded or collapsed.

            When I work in V-Ray, I want to see everything all of the time. Scrolling up and down is easy but having to click to expand everything to gain complete visibility is very disruptive. The collapsed panels are a total hinderance to me. I realize that to many they may make V-Ray's UI less overwhelming but it's the opposite for me. Having to manually expand them on every new unvisited page makes the interface more overwhelming when all I want is just to see everything, everywhere at all times without having to expand the panels whenever I first go into a material, light, settings view, etc for the first time during a new session. Sometimes I end up having to do this manual expansion of all parent and child panels multiple times during one Rhino session. When V-Ray's interactive rendering viewport view mode mysteriously disappears from Rhino as it still does quite often, the only way to restore it is to switch the Current Renderer to Rhino Render and then back to V-Ray, which of course resets all the panels to their default collapsed state. That one really rubs salt into the wound.

            If the best you guys can do is remember the state of each panel when the file is saved and restore their states, I'd totally take it and would be more than happy with that because I'd only have to do this once per session. Hell, I could even create my own blank starter template where I've manually expanded all the available panels that I can then save the state of and start a new studio from. If there's just one UI gripe that I was allowed to fix and then never again would be allowed any other requests, it would hands down be this. Can you nudge the UI team a bit and remind them that their power users have been very patiently waiting for this since VR4. In an interface like the Asset Editor that users can spend a lot of time in and is prone to crashing/hanging just like all rendering interfaces are, a harmless UI behavior such as numerous expandable panels that are always collapsed by default begin to really add up to degrade the user experience. Just like we have a Configuration to toggle Basic or Advanced, there should be one to Collapse or Expand all panels by default for the project.
            Last edited by TopRamen; 19-06-2023, 03:31 PM.

            Comment

            Working...
            X