0
$\begingroup$

i have a script to duplicate an object, and place the duplicates at random coordinates around a spheres surface, and then point those objects away from the center of the sphere. It almost works but the calculation for the rotation of the objects is off by just enough for it to not look good at all.

I've search a lot for what i am doing wrong, but the very few solutions I've found are very out of date.

Here is my code, assumes sphere is at 0,0,0 world coordinates:

def PlaceSpike():
    worldLocation = Vector((0.0,0.0,0.0))

    radius = 2.4

    latDeg = randint(0, 360)

    lonDeg = randint(0, 360)

    scale = 0.1

    #Create new object to be used
    pin = DuplicatePin( 'Spike', bpy.data.objects['Cone'], bpy.data.materials['pin'], 'Diffuse BSDF', Color((1.0,0.0,0.0)))

    latRad, lonRad = radians( latDeg ), radians( lonDeg )


    x = cos( latRad ) * cos( lonRad )
    y = cos( latRad ) * sin( lonRad )
    z = sin( latRad )


    location = Vector((x, y, z)) * radius


    locationFromWorld = location + worldLocation
    scale3D = (scale, scale, scale)

    aroundZ = Quaternion( (0, 0, 1), lonRad )
    aroundY = Vector( (0, -1, 0) )
    aroundY.rotate( aroundZ )
    aroundX = Quaternion( aroundY, latRad )

    rotation = Quaternion( baseRotationQuat )
    rotation.rotate( aroundZ )
    rotation.rotate( aroundX )

    pin.scale = scale3D
    pin.location = location
    pin.rotation_euler = rotation.to_euler( 'XYZ' )


for x in range(10):
    PlaceSpike()

Here is what it looks like: enter image description here

I'm having a very hard time figuring out what to do, I'm not even sure anymore if i am doing it the right way and would appreciate the help, thank you.

$\endgroup$
1
$\begingroup$

You can use Euler rotations (as they usually are in the UI).

The trick is to know from what these rotations will start, considering your coordinate system (longitude, latitude).

  • Longitute starts along the X axis.
  • Latitude around Z.

Also, Blender rotations are clockwise, so you need to minus the latRad (as math convention is counter clockwise).

So, from the image in your question, as the spike is up, you need to place it along X rotating 90 around Y and remove the latRad.

x = cos( latRad ) * cos( lonRad )
y = cos( latRad ) * sin( lonRad )
z = sin( latRad )

location = Vector((x, y, z)) * radius

locationFromWorld = location + worldLocation
scale3D = (scale, scale, scale)

pin.scale = scale3D
pin.location = location

pin.rotation_euler = Euler((0,(pi / 2)-latRad,lonRad)) # << Euler rotation from the given angles
| improve this answer | |
$\endgroup$
  • $\begingroup$ That works perfectly, also note: i hadn't centered the spike point of origin properly after moving it from 0,0,0. Thanks. $\endgroup$ – Thiedent Mar 15 at 23:17

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.