4
$\begingroup$

I'm looking to make a driver that outputs a random value between a specific range (in this case -1 to 1) as a way to randomly change the factor value of the Simple Deform modifier. So that I can duplicate an object, and the factor is a random value, giving unique shapes for each, but within a range of acceptable values.

I've taken a look at other questions/answers, but I haven't found anything that pertains to my situation, or that I don't understand how it's being done.

I'm not looking for other workflows or other ways to go about what I'm doing with the modifiers. I'm specifically looking for a way to make a random driver that outputs numbers within a range. Nothing more. I'm not interested in animation nodes either, not at the moment anyway, so that's not an acceptable answer either.

I'm not wanting to sound rude or anything. Please just answer the question as it is in the topic.

Thanks.

$\endgroup$
  • 4
    $\begingroup$ IMO prompting for the type of answer you are after is fine. Listing those you don't want isn't., and sounds picky. It's your question and you get accept an answer that is right for you. This isn't a restaurant, Let others cook up answers, that may be of benefit to others. Not wanting to sound rude consider voting more. $\endgroup$ – batFINGER Jul 20 at 11:06
  • 1
    $\begingroup$ It's a waste of time to get answers that're completely extraneous to what I've asking. Time and again, I've asked questions, and like clockwork I'll get responses that have nothing to do with the question I've asked. Instead, questioning why I'm doing something a certain way. I know what I'm doing (I've been at it 12 years).There's reasons behind why I approach a problem the way I do. If I hit a snag, and come here to ask something, I expect an answer to the specifications that I ask for so they fit the project I'm working on. Not others. I'll help others on my own time by answering questions. $\endgroup$ – AxiomDes Jul 21 at 3:42
4
$\begingroup$

It's a bit hacky but you can use the python hash method to generate a "random" number, for example using the name of each object since they must be different from each other.

The caveat is it isn't by default in the driver namespace, but you can very easily add it in. You can choose to permanently add it to the driver namespace for all sessions or just for the current session. More information in this answer.

import bpy

# Uncomment if you want the hash method to be permanently added to the driver namespace
#@bpy.app.handlers.persistent
#def setup_driver(*args):
#    bpy.app.driver_namespace["hash"] = hash

#bpy.app.handlers.load_post.append(setup_driver)
#setup_driver()

# Use this if you want the hash method to be added to the driver namespace for this session only
bpy.app.driver_namespace["hash"] = hash

How to run a script

I believe most string hashes will be very large numbers, so you can divide the resulting hash by a high number and take the modulo (%) by 1 to get a value between 0 and 1.

enter image description here

Example with a driver on the Z coordinate of my cubes with a modulo of 10 that I simply duplicated along the Y axis.

enter image description here

You can manipulate the % value to get the desired range. Example with the simple deform bend modifier where I used (2* pi).

enter image description here

enter image description here

If you want to restrict between 0 and 1, use % 2 - 1

| improve this answer | |
$\endgroup$
  • $\begingroup$ Strongly consider using the "use self" option and use hash(self.name) / 10000 % 1 $\endgroup$ – batFINGER Jul 20 at 10:48
  • $\begingroup$ Worked perfectly. Thanks a ton. Clear, concise, and exactly what I asked for. I couldn't get the self.name to work though. But the original answer works just fine for what I need. $\endgroup$ – AxiomDes Jul 21 at 3:53
  • $\begingroup$ @AxiomDes You have to enable "Auto execute python scripts" under Preferences/Save & Load to be able to use self. However depending on your worklflow this could cause security issues. Your choice $\endgroup$ – Gorgious Jul 21 at 6:52
  • $\begingroup$ Yeah no worries there. Everything works well enough. Though I have found that sequential duplicates end up looking pretty similar. So like Object.001 and Object.002 look almost identical. The values are changing though, it's just that it takes a few duplicates to get a shape that's completely different than the one before. That might have just been me messing up somewhere though. $\endgroup$ – AxiomDes Jul 21 at 8:49
  • $\begingroup$ Well hashes are not completely random, you can only be assured that they will be different (I'm not even sure about that), not that the difference between any of them will be significant. You could for example add in the location of the object to the driver to add another element of differenciation. But if you're not going for animation you should definitely use the noise.random as in @batFINGER's answer. You can also change the driver expression, maybe the dividing number is not well suited in this case $\endgroup$ – Gorgious Jul 21 at 8:52
7
$\begingroup$

Noise module is in the driver namespace

For our convenience the mathutils.noise module is added to the driver namespace by default. As have all members of mathutils and most of math module.

>>> bpy.app.driver_namespace['noise']
<module 'mathutils.noise'>

There are a number of options for randoms, for a simple range (-1.0, 1.0) can type #2 * noise.random() - 1 directly into a non-driven field. The hash # signifies make this a driver.

enter image description here

after, (good some random in range.

enter image description here

Click within the property can edit it directly (notice no hash since it is already a driver, signified by purple)

enter image description here

Note these values will change randomly for each frame. Remove the driver to "keep" a value.

Using self in drivers

Further to my comment re @Gorgious's answer can use self in drivers.

enter image description here

If the driver is on a modifier then self will be the modifier, self.id_data the object the modifier belongs to.

Simple test script, adds a method test to the driver namespace. The object the driver is on is passed to the method. The hash of the object's name is divided by some seed and the remainder returned.

Hash can be either positive or negative, so the values should fall within the range of (-1, 1)

import bpy
from bpy.app import driver_namespace as dns
from math import modf

seed = 203137

def test(ob):
    r = modf(hash(ob.id_data.name) / seed)[0]
    return r

dns["test"] = test
| improve this answer | |
$\endgroup$
  • 1
    $\begingroup$ It's very handy :) but you should also mention that : - If using it in animation, the noise value will change every time the frame changed and - you have to enable "Auto execution" of python scripts which can cause security issues $\endgroup$ – Gorgious Jul 20 at 10:14
  • $\begingroup$ Thanks. Yep drivers require that setting. It has been well covered. Having a driver constantly calculate to return same value IMO isn't sensible usage of a driver either. Typing or pasting simple expression above into a field once or a simple script to copy / assign value or a getter setter prop would be a much more straight forward approach. $\endgroup$ – batFINGER Jul 20 at 10:54
  • $\begingroup$ @Gorgious never used it much, I think the noise.turbulence method could do this somewhat. Just as the noise modifier on same fcurve produces same result. There was a q re something similar ... or how to use... will have a quick search. $\endgroup$ – batFINGER Jul 20 at 11:15
  • $\begingroup$ @Gorgious added the use self part re your answer, as proof of concept, for those whom, unsurprisingly, "couldn't get it to work" $\endgroup$ – batFINGER Jul 21 at 9:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.