Forgot password?

Create an account!

Forum

« back

RhinoScript – orienting face to camera: almost solved

Messages

Please log in to write a message.

  • 9. mmpolites (Jul 30, 2010 03.01):

    Does anyone know a way to do this with nurbs and not meshes?

  • 8. Hanno (Apr 13, 2009 21.44):

    Thanks for uploading!

    Hanno

  • 7. dingle (Apr 07, 2009 23.19):

    hey, never had a chance to wrap this one up successfully, but it works, just sometimes need to refreshed a few times. here's the flawed but functional version:

    www.rhinoscript.org/scripts/65

    and here's the "refresh" version that just updates the group with a click

    www.rhinoscript.org/scripts/66

  • 6. Hanno (Mar 18, 2009 11.26):

    Hi,
    you either want to rotate by 90-angle or by 90+angle degree (because thats "the other way round"), then it should work.

    Hanno

  • 5. dingle (Mar 17, 2009 01.58):

    hanno,
    great tip with the cross product. that's a lot simpler than how i was thinking about it. but i'm still missing a step, and i can't figure it out. the script works, but it takes 4 runs to make it work properly for all selected objects. baffling to me.
    here's what i have so far. (going to incoporate some group functions later to make it easier to make a toolbar button - hence the first sub)

    Option Explicit
    'Script written by AM
    'Script version Sunday, March 15, 2009 7:17:30 PM

    Call AddObjects()
    Sub AddObjects()
           
            Dim strObjects
            strObjects = Rhino.GetObjects("Select meshes to rotate", 32, True)
            If IsNull(strObjects) Then
                    Rhino.Print "No valid objects selected."
                    Exit Sub
            End If
            RotateObjectsToCamera(strObjects)
                   
    End Sub


    Function RotateObjectsToCamera(strObjects)
           
            Dim arrCam, arrVertices, arrVertex, strBottomLine, arrMid
            Dim arrLine1, arrLine2, arrAngle, dblRotateAngle
            Dim arrNormals, arrPlane, arrVecCamToMid, arrNormalAngle
            Dim i


           
            arrCam = Rhino.ViewCamera
           
            Rhino.EnableRedraw(False)       
            For i=0 To UBound(strObjects)
                   
                    'OBJECT TYPE
                    Select Case Rhino.ObjectType(strObjects(i))
                            Case 8
                                    arrNormals = Rhino.SurfaceNormal(strObjects(i))
                                    arrVertices = Rhino.SurfacePoints(strObjects(i))
                            Case 32
                                    arrNormals = Rhino.MeshVertexNormals(strObjects(i))
                                    arrVertices = Rhino.MeshVertices(strObjects(i))
                    End Select
                   
                    If IsNull(arrNormals) Then Exit For
                    If IsNull(arrVertices) Then Exit For
                   
                    'CONSTRUCTION LINES
                    arrVertex = arrVertices(2)
                    strBottomLine = Rhino.AddLine(arrVertices(0), arrVertex)
                    arrMid = Rhino.CurveMidPoint(strBottomLine)

                    arrLine1 = Array(Array(arrCam(0),arrCam(1)), Array(arrMid(0),arrMid(1)))
                    arrLine2 = Array(Array(arrVertices(0)(0),arrVertices(0)(1)), Array(arrVertex(0),arrVertex(1)))
                    arrAngle = Rhino.Angle2(arrLine1, arrLine2)
                    If Not IsArray(arrAngle) Then Exit For
                   
                    'NORMAL ANALYSIS. FRONT VS BACK, CW VS CCW
                    arrPlane = Rhino.PlaneFromNormal(arrVertices(0), arrNormals(0))
                    arrVecCamToMid = Rhino.VectorCreate(Array(arrCam(0),arrCam(1)), Array(arrMid(0),arrMid(1)))
                   
                    Dim u0  : u0  = Rhino.VectorUnitize(arrVecCamToMid)
                    Dim u1  : u1  = Rhino.VectorUnitize(arrPlane(0))  
                    Dim cross : cross = Rhino.VectorCrossProduct(u0, u1)
                    'Rhino.Print Rhino.Pt2Str(cross)
                   
                    'ALREADY PERPENDICULAR
                    If cross(2) = 0 Then Exit For

                    'FRONT
                    If cross(2) < 0 Then
                            'Rhino.Print "Angle: " & CStr(arrAngle(0))
                            dblRotateAngle = (CDbl(arrAngle(0)))-90
                            Rhino.RotateObject strObjects(i), arrMid, dblRotateAngle
                    End If
           
                    'BACK
                    If cross(2) > 0 Then
                            'Rhino.Print "Angle: " & CStr(arrAngle(0))
                            dblRotateAngle = 90-(CDbl(arrAngle(0)))
                            Rhino.RotateObject strObjects(i), arrMid, dblRotateAngle
                    End If
                   
                    Rhino.DeleteObjects Array(strBottomLine)
                   
            Next
            Rhino.EnableRedraw(True)
    End Function
  • 4. Hanno (Mar 16, 2009 13.08):

    Hi,

    that seems to me to be the typical 180 degree problem - you will never get an angle between two vectors that is > 180, so from the angle alone you cannot know if you should rotate clockwise or counterclockwise.
    To solve this, you can check if the cross product of your vectors points in positive or negative z direction, and use this to control your rotation direction.

    Hope that helps!

    Hanno


    PS: Would be great if you added the finished script to our script library!

  • 3. dingle (Mar 16, 2009 12.49):

    also, i've found that if i run the script 3 times, it corrects all the ones that rotate the wrong direction.
    perhaps there's a much simpler way to do this than comparing the mesh's normal angle to the camera vector.

  • 2. dingle (Mar 16, 2009 01.19):

    wow, sorry about that getobjects string message on line 9... my bad for not double checking!
    please feel free to edit that out of my post.

  • 1. dingle (Mar 16, 2009 01.18):

    hey all,
    i wonder if anyone has already done this? we have a library of 2D people mapped onto 4-vertex meshes, and it would be super good to have an instantaneous way to re-orient the people to face the camera. would actually save hours in rendering and photoshop times. kinda like the 3ds max lookat function, but not as insanely dumb and tedious. just want all the people to face the camera with the click of a button.
    so. i've almost got it. (even swiped some dot product code from the rhinoscript wiki.) but there's a hiccup somewhere. i think it has something to do with declaring variables inside the loop? when i run the script, sometimes the "normal angle" is calculated wrong, causing the meshes to rotate the wrong direction. i should be able to select any face, no matter which direction it's rotated, and have it orient itself to the camera.
    actually, i think it might have something to do with choosing the Y direction of the planefromnormal instead of the X. sometimes it wants to be X, sometimes Y?
    anyway, let me know if i should post a rhino file... if you'd like to recreate my situation, just copy around a flat 4-vertex mesh a bunch of times.
    as always, thanks a million for looking.

    Call OrientMeshToCamera()
    Sub OrientMeshToCamera()
           
            Dim strObjects, arrCam, arrVertices, arrVertex, strBottomLine, arrMid
            Dim arrLine1, arrLine2, Line1, Line2, arrAngle, dblRotateAngle
            Dim arrNormals, arrPlane, arrVecCamToMid, arrNormalAngle
            Dim i
           
            strObjects = Rhino.GetObjects("Select motherfuckers", 32, True, True)
            If IsNull(strObjects) Then Exit Sub
           
            Rhino.EnableRedraw(False)
           
            For i=0 To UBound(strObjects)
           
                    arrCam = Rhino.ViewCamera
                    arrVertices = Rhino.MeshVertices(strObjects(i))
                    If IsNull(arrVertices) Then Exit For
                   
                    'daniel case
                    arrVertex = arrVertices(2)
                    strBottomLine = Rhino.AddLine(arrVertices(0), arrVertex)
                    arrMid = Rhino.CurveMidPoint(strBottomLine)

                    arrLine1 = Array(Array(arrCam(0),arrCam(1)), Array(arrMid(0),arrMid(1)))
                    arrLine2 = Array(Array(arrVertices(0)(0),arrVertices(0)(1)), Array(arrVertex(0),arrVertex(1)))
                    arrAngle = Rhino.Angle2(arrLine1, arrLine2)
                    If Not IsArray(arrAngle) Then Exit For
                   
                    'NORMAL ANALYSIS. FRONT VS BACK.
                    arrNormals = Rhino.MeshVertexNormals(strObjects(i))
                    arrPlane = Rhino.PlaneFromNormal(arrVertices(0), arrNormals(0))
                    arrVecCamToMid = Rhino.VectorCreate(Array(arrCam(0),arrCam(1)), Array(arrMid(0),arrMid(1)))
                   
                    Dim u0  : u0  = Rhino.VectorUnitize(arrVecCamToMid)
                    Dim u1  : u1  = Rhino.VectorUnitize(arrPlane(1))  
                    Dim dot : dot = Rhino.VectorDotProduct(u0, u1)

                    If (dot < -1.0) Then
                            dot = -1.0
                    ElseIf (dot > 1.0) Then
                            dot = 1.0
                    End If
                   
                    arrNormalAngle = Rhino.ToDegrees(Rhino.ACos(dot))
                    'Rhino.Print "Normal Angle: " & CStr(arrNormalAngle)
                   
                    'FRONT
                    If arrNormalAngle <= 90 Then
                            Rhino.Print "Angle: " & CStr(arrAngle(0))
                            dblRotateAngle = (CDbl(arrAngle(0)))-90
                            Rhino.RotateObject strObjects(i), arrMid, dblRotateAngle
                    End If
           
                    'BACK
                    If arrNormalAngle > 90 Then
                            Rhino.Print "Angle: " & CStr(arrAngle(0))
                            dblRotateAngle = 90-(CDbl(arrAngle(0)))
                            Rhino.RotateObject strObjects(i), arrMid, dblRotateAngle
                    End If
                   
                    Rhino.DeleteObjects Array(strBottomLine)
                   
            Next
           
            Rhino.EnableRedraw(True)
           
    End Sub
Recommend

Why are these buttons gray?