Announcement

Collapse
No announcement yet.

Spawn Actor, positioning help needed. Align locations of components of two actors

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

    Spawn Actor, positioning help needed. Align locations of components of two actors

    Ok, two actors.

    Click image for larger version

Name:	3Nq4iYt.png
Views:	1
Size:	6.2 KB
ID:	1140381

    Each actor has the center point (in red) and four components, each facing away from the center, snapped to 90 degrees.

    Actor 1 already exists in the map. On Actor 1, I am running a Event Begin node to spawn Actor 2.



    The goal is to feed in a component of Actor 1 and a component of Actor 2 and have Actor 2 positioned in such a way that it is rotated correctly and its component lined up with that of Actor 1. I realize this is an awful explanation, so here's some pictures.


    Ex: I feed in component A and F ("Attach" Actor 2 at component F to Actor 1 at component A)

    Click image for larger version

Name:	qIjoSGT.png
Views:	1
Size:	4.5 KB
ID:	1140382

    Actor 1 remains stationary, Actor 2 is rotated and moved to line up with Actor 1 at the specified components.

    One more example: I feed in Component C and G

    Click image for larger version

Name:	ZAB2aUf.png
Views:	1
Size:	4.7 KB
ID:	1140383


    I want to do this completely relative, without using stuff like "If rotation is 90 degrees, move Actor 2 400 units on the X axis".



    So here's what I have so far.

    Feed in Component1 (the component from Actor 1) and Component2 (the component from Actor 2)
    • Spawn Actor 2, the transform doesn't matter (I can't position it until I can evaluate the components on Actor 2).
    • Set Actor 2's rotation to be Component1's rotation +180 degrees
    • Position Actor 2..???


    I have no idea how to properly position Actor 2.

    If I do
    (Get Actor 1's Location + Get Component1's Relative Location), this returns the world coordinates for Component1
    From there, I want to make sure I move Actor 2 out in the right direction, so I think I would need to use "Get Forward Vector" of Component1 and somehow obtain either X or Y (how do I know which one is right?) of Component2 and "Get Right Vector" of Component 1 and the X or Y of Component 2.

    Ex: Attach A and G

    Click image for larger version

Name:	nq3dIFF.png
Views:	1
Size:	7.7 KB
ID:	1140384

    In this case, sure.. I know that I would need to move up on the Y axis and right on the X axis, but the idea is that this is all dynamic and relative. After Actor 2 is rotated, I need to get the number of forward units between Actor 2 and Component2 and move forward that many. Then, I need to get the number of right units between Actor 2 and Component2 and move right that many.

    I am doing a terrible job explaining this and I really hope someone understands my issue.



    I need to set the location of the two components to be identical. The two actors will have rotation 180 degrees difference.

    #2
    First. make array of Transform values for each component. Store there relative rotations and location to actor component. (Eg. COLOR="#800080"]Transform_Component_Array[/COLOR])

    You can automate it, if you make array of components (Component_Pt_Array), feed it with all component pointers (references), and read their relative transform values, then fed to (Transform_Component_Array)

    Now you should have array with relative transform values. ie relative location, relative rotation and scale, all in single array.

    You spawned Actor 1, now its time to find Actor 2 transformation.
    Decide on component ID of actor 1, (ie A=0, B=1 C=2 D=3 and so on) and Actor 2.
    Read both components RELATIVE transform from (Transform_Component_Array)

    Location of Actor B is. "Actor A LOC" + "Actor A component relative LOC" - "Actor B component relative LOC" , (because actor B component is facing opposite direction)

    Now I am not sure about rotation, but same as above should work. Also you can get gimball effect here, rotation may be quite tricky for 3d, check it first for 2d variant.
    Rotation of Actor B should be: "Actor A ROT" + "Actor A component relative ROT" - "Actor B component relative ROT"

    Comment


      #3
      Originally posted by Nawrot View Post
      First. make array of Transform values for each component. Store there relative rotations and location to actor component. (Eg. COLOR="#800080"]Transform_Component_Array[/COLOR])

      You can automate it, if you make array of components (Component_Pt_Array), feed it with all component pointers (references), and read their relative transform values, then fed to (Transform_Component_Array)

      Now you should have array with relative transform values. ie relative location, relative rotation and scale, all in single array.
      I did plan on putting them into an array as I plan to randomly pick a component from each actor by generating a random int and using it as the index, but I don't think it's needed for now... I can just get each component manually.

      Originally posted by Nawrot View Post
      Location of Actor B is. "Actor A LOC" + "Actor A component relative LOC" - "Actor B component relative LOC" , (because actor B component is facing opposite direction)
      .. it's that simple? Subtract Actor B's relative location? ... huh. I have a hard time visualizing things so when I try to imagine these scenarios my brain doesn't function well. If that works, that's amazing and much simpler than I was making it.

      Originally posted by Nawrot View Post
      Now I am not sure about rotation, but same as above should work. Also you can get gimball effect here, rotation may be quite tricky for 3d, check it first for 2d variant.
      Rotation of Actor B should be: "Actor A ROT" + "Actor A component relative ROT" - "Actor B component relative ROT"
      Don't know what you mean by Gimball Effect. For rotation, I think it's fine. I'm just going to set Actor B's rotation to be the same as Actor A's component. I've tested this and it seems to work just fine. But I need to do this BEFORE I set the location, right? Because it will affect the world coordinates and the "Get Actor B's relative location" return
      Last edited by Chumble; 11-03-2014, 01:03 PM.

      Comment


        #4
        Ok, it didn't work.

        Here's the two actors with their exact dimensions as each would be viewed in the component window.

        Click image for larger version

Name:	qujiSRi.png
Views:	1
Size:	255.4 KB
ID:	1060560

        Ok, so I place Actor 1 at 0,0. Then, I want to attach Actor 2 to Actor 1, using C4 for each component as the attach point.

        In order for Actor 2 to be placed correctly, it needs to be placed at 500,-100 at Actor 1's component +180.

        Note: The actual locations for many of the components end in 95 because I offset it inside for other reasons, but I move it manually. Don't worry about the 5 unit difference, I'm handling that.

        Click image for larger version

Name:	7qjZrNe.png
Views:	1
Size:	181.6 KB
ID:	1060561

        Originally posted by Nawrot View Post
        Location of Actor B is. "Actor A LOC" + "Actor A component relative LOC" - "Actor B component relative LOC" , (because actor B component is facing opposite direction)
        I can't always add or subtract the vector. For the example above, if I get the world location of Actor 1's component and ADD the relative location of Actor 2's component, it works.
        If I changed it up so I'm attaching to "C1" on Actor 1 instead, I need to SUBTRACT the relative location Actor 2's component.
        In order to position it at C2 or C3 on Actor 1, I would need to Add/Subtract X/Y for one, and switch it up for the other.

        SO.. just flat out adding or subtracting Actor 2's component will not work. Any other ideas?

        Comment


          #5
          New pictures make it much more clear what you want achieve.

          Make components locations use positive values. Ie. right and up is positive, and left and down negative. Vectors in ue use that so you should not fiddle with it to avoid confusion. Your problem is quite simple (in 2d).

          So we have ActorA with ComponentA and ActorB with ComponentB. We want connect ActorB to ACtorA.

          First we need to rotate ActorB . Then we add ActorA world position with ComponentA and rotated componentB local vectors.

          Desired rotation of ActorB is: Rotation_ActorA + Rotation_ComponentA + 180 - Rotation_ComponentB

          When you have this done test only rotations if it (hopefully) works.

          Now we need to add vectors: World_location_ACtorA + Relative_location_ComponentA - Relative_location_ComponentB

          ps. This is great exercise (and usefull BP to have), I will probably toy a bit with this.

          PPS. I assume that all Actors orginal rotations are zero. Like you take them out of box then rotate and move, else you need to add current world rotation and location of ActorB into formulas.
          Last edited by Nawrot; 11-04-2014, 09:02 AM. Reason: colors

          Comment


            #6
            Originally posted by Nawrot View Post
            Make components locations use positive values.
            Are you saying I shouldn't have any component with a negative value? This would offset the root from 0,0 and it's a bit weird.. why would I do that?

            Originally posted by Nawrot View Post
            Desired rotation of ActorB is: Rotation_ActorA + Rotation_ComponentA + 180 - Rotation_ComponentB
            Rotation_ComponentA + 180 will always be what I need for ActorB's rotation, so I'm good on that front.



            Originally posted by Nawrot View Post
            Now we need to add vectors: World_location_ACtorA + Relative_location_ComponentA - Relative_location_ComponentB
            But .. this is just what you said before, isn't it?


            One important point here I'm not sure if you missed (I did, in an earlier post), rotating an actor does not affect the relative locations of its components. So it doesn't matter how ActorB is rotated, Adding WorldA+RelativeA and subtracting RelativeB will only work when moving in the negative X/Y direction.
            Last edited by Chumble; 11-04-2014, 10:13 AM.

            Comment


              #7
              Hello,
              not sure my method will be ok for you but it is better you don't like it than you don't know it ^^ : i use only world location. Actor A have position (Xa,Ya) and Actor B (Xb,Yb)
              Z : Offset from Actor A (0,0) to Actor A c 4. (295)
              x : X offset from Actor B (0,0) to Actor B c4 (195)
              y : Y offset from Actor B (0,0) to Actor B c4 (100)

              Then on a rotation condition :
              A : rot 0 (Xa,Ya) B : rot 180 (Xa-z-x) , (Ya-y) : with your numbers : 0 (0,0) / 180 (0-295-195 ,0 -100)
              A : rot 90 (Xa,Ya) B : rot 270 (Xa-y) , (Ya+z+x) : with your numbers : 90 (0,0) / 270 (0-100, 0+ 295+195)
              A : rot 180 (Xa,Ya) B : rot 0 (Xa+z+x) , (Ya+y) : with your numbers : 180 (0,0) / 180 (0+295+195 ,0+ 100)
              A : rot 270 (Xa,Ya) B : rot 90 (Xa+y) , (Ya-z-x) : with your numbers : 270 (0,0) / 90 (0+100, 0 -295-195)

              I considered + x on the right and +y on the top.
              Last edited by Fen; 11-04-2014, 10:56 AM.

              Comment


                #8
                Originally posted by Fen View Post
                Hello,
                not sure my method will be ok for you but it is better you don't like it than you don't know it ^^ : i use only world location. Actor A have position (Xa,Ya) and Actor B (Xb,Yb)
                Z : Offset from Actor A (0,0) to Actor A c 4. (295)
                x : X offset from Actor B (o,o) to Actor B c4 (195)
                y : Y offset from Actor B (o,o) to Actor B c4 (100)

                Then on a rotation condition :
                A : rot 0 (Xa,Ya) B : rot 180 (Xa-z-x) , (Ya-y) : with your numbers : 0 (0,0) / 180 (0-295-195 ,0 -100)
                A : rot 90 (Xa,Ya) B : rot 270 (Xa-y) , (Ya+z+x) : with your numbers : 90 (0,0) / 270 (0-100, 0+ 295+195)
                A : rot 180 (Xa,Ya) B : rot 0 (Xa+z+x) , (Ya+y) : with your numbers : 180 (0,0) / 180 (0+295+195 ,0+ 100)
                A : rot 270 (Xa,Ya) B : rot 90 (Xa+y) , (Ya-z-x) : with your numbers : 270 (0,0) / 90 (0+100, 0 -295-195)

                I considered + x on the right and +y on the top.
                Yeah, I might need to use this method. I was really hoping to avoid making a condition out of it, but I guess it's not that bad.

                Comment


                  #9
                  Originally posted by Chumble View Post
                  So it doesn't matter how ActorB is rotated, Adding WorldA+RelativeA and subtracting RelativeB will only work when moving in the negative X/Y direction.
                  Because your components have mirrored coordinate system. Use same coordinate system for components as vectors have in unreal use. IE. positive for right and up, else this will always confuse you.

                  And if you do not use rotation then why you rotate your components ie. Rotation_ComponentA + 180 ? Always rotating ActorB by 180deg will not work for all cases. I may be confused with rotation because of those small green arrows in first post. If you want connect Actor1 pointB with Actor2 point F (from first post) you need to rotate actorB. That is why i assumed green Arrows to represent direction of connecting joint. And thus need of rotation for actorB.

                  For me it looks like you are mirroring components around 0-x and 0-y, then you rotate it 180deg. So for sure my vector adding formula will not work for this case. Simplify your problem, split into tiny steps.

                  Comment


                    #10
                    Originally posted by Nawrot View Post
                    Because your components have mirrored coordinate system. Use same coordinate system for components as vectors have in unreal use. IE. positive for right and up, else this will always confuse you.

                    And if you do not use rotation then why you rotate your components ie. Rotation_ComponentA + 180 ? Always rotating ActorB by 180deg will not work for all cases. I may be confused with rotation because of those small green arrows in first post. If you want connect Actor1 pointB with Actor2 point F (from first post) you need to rotate actorB. That is why i assumed green Arrows to represent direction of connecting joint. And thus need of rotation for actorB.

                    For me it looks like you are mirroring components around 0-x and 0-y, then you rotate it 180deg. So for sure my vector adding formula will not work for this case. Simplify your problem, split into tiny steps.

                    Yeah, I'm really bad at explaining things. I was trying to simplify it by removing the context, but maybe it will help. The shapes are rooms of a randomly generated map. The components are doorways.

                    The entire thing will end up building many many rooms, but for now I am simply trying to get one single room to spawn correctly. I have placed RoomA on the map and its event graph will perform the following functions:

                    Note: "Doorways" are the vector components of the actor. There are 4 per room, already positioned and rotated correctly.
                    1. Randomly pick a doorway (let's call it DoorA) from RoomA (The 600x600 square room)
                    2. Randomly pick a new room to spawn (Let's simplify this to always picking "RoomB", the 400x400 L-Shaped room)
                    3. Randomly pick a doorway from RoomB (DoorB)
                    4. Align DoorB with DoorA. This is obviously the part we're focusing on.
                      1. Rotate RoomB to the correct rotation so that when DoorB is aligned with DoorA, the rooms are not overlapping. How can I accomplish this?
                        • I just typed up exactly what I had been doing and realized it is absolutely wrong. I don't know what I was thinking. It worked for the specific scenario I was testing but it wont for other cases.
                        • Using the above graphs/drawings as a reference.. if I place RoomB/C4 at RoomA/C4, it needs to be rotated 180 degrees.
                          If I place RoomB/C4 at RoomA/C3, it needs to be rotated 270 degrees.
                          In the end, DoorB needs to be DoorA + 180 degrees.
                          I can get DoorA's rotation, add 180 degrees, then subtract DoorB's rotation and apply it to RoomB... which is exactly what you said before. Ok.
                      2. Change DoorB's location to be equal to DoorA's location.
                        • Here is where I may need to incorporate Fen's solution. I may need to check DoorA's rotation and perform the movement calculations based on that.
                        • The only way I can see this working dynamically is by determining the amount of units both FORWARD and RIGHT that RoomB should be away from DoorA. I dug up some old geometry lessons to see if I could find anything helpful, but unfortunately I don't think there's anything I can do if I only know it's a 90 degree triangle and the length of the hypotenuse.
                          Click image for larger version

Name:	9ll3h8r.png
Views:	1
Size:	10.9 KB
ID:	1060594
                        • I could cheat. I could, in addition to having a vector for each door, have another vector at each side of the room right in the middle.
                          Click image for larger version

Name:	PAoYeTe.png
Views:	1
Size:	9.7 KB
ID:	1060595
                          In doing this, if I was looking to calculate DoorA, I could use the distance from SideA to the center to get the forward vector and the distance from SideA to DoorA to get the right vector.
                          I don't like flooding my components with extra stuff just to cheat, but I don't know what else there is.





                    I cheated - hardcore. Gave each room an array containing the appropriate offsets for each door. So I know if I pick "door 1", I need to go forward 195 units and right -100 units. I'm not proud of cheating but I honestly couldn't find another way and I'm ready to move on to another part of this project. Thanks for the replies and if anyone has any better ideas, feel free to post.
                    Last edited by Chumble; 11-05-2014, 01:05 AM. Reason: avoid double posting

                    Comment


                      #11
                      I played with this a bit yesterday, but had power outage, and lost some time.

                      I have one problem unsolved that is strictly related to your idea. I just cannot find vector math node that can add 2 rotators, or give rotation from one rotator to another. This can be done by simply breaking rotator and adding or substracting rotations, but then it will introduce gimball effect (2d safe, not so in 3d). I know how to do that math, but i am hopelessly lost about what this is called in unreal kismet.

                      So for now i am lurking in docs and answer hub.

                      Comment


                        #12
                        Originally posted by Nawrot View Post
                        I played with this a bit yesterday, but had power outage, and lost some time.

                        I have one problem unsolved that is strictly related to your idea. I just cannot find vector math node that can add 2 rotators, or give rotation from one rotator to another. This can be done by simply breaking rotator and adding or substracting rotations, but then it will introduce gimball effect (2d safe, not so in 3d). I know how to do that math, but i am hopelessly lost about what this is called in unreal kismet.

                        So for now i am lurking in docs and answer hub.
                        I'm still not sure what is meant by "gimball effect". Is that where the rotation becomes slightly askew and ends up being 89.99999 instead of 90, for example? I've solved this in the past by saving the rotation to a variable then when I wish to obtain the actor's rotation I use the variable instead of "Get actor rotation", though I had no idea what was causing it.

                        Last night I went forward with Fen's idea and said

                        1) If RoomB's rotation is 0, subtract the relative location of DoorB from the world position of DoorA
                        2) If RoomB's rotation is 90, <some mess involving subtracting the Y from one and the X from the other>
                        3) If RoomB's rotation is 180, add the relative location of DoorB and the world position of DoorA
                        4) If RoomB's rotation is 270, <some mess involving subtracting the Y from one and the X from the other>

                        It worked.. as long as I always used the same door from RoomA. If I tried to use a different door from RoomA, RoomB's rotation might be 90 degrees, but I would need to use 1 or 3 from the above calculations instead of 2. I started making this giant thing to encompass every possible configuration but it got so messy and I was tired so I deleted it all and just hardcoded some values.

                        In hindsight, I think I could have done some calculation with RoomA's rotation and it would have fit into those 4 calculations. Instead of just using RoomB's rotation, I think I could have used RoomB's rotation - RoomA's rotation. Maybe.

                        Comment


                          #13
                          If you use 3 variables for your 3 offset (and maybe a fourth one for rotation) and do a function with those variables (with formulas i gave you for example), you'll can change them when you want with arrays registering them when generating your leveland you'll not have to hardcode.

                          Comment


                            #14
                            Originally posted by Fen View Post
                            If you use 3 variables for your 3 offset (and maybe a fourth one for rotation) and do a function with those variables (with formulas i gave you for example), you'll can change them when you want with arrays registering them when generating your leveland you'll not have to hardcode.
                            I misspoke. Basically what I did was create two arrays on each room.

                            Array "Doors" simply holds each doorway.
                            Array "Offsets" holds the offsets for each doorway.


                            So for a square room with 4 centered doors, it looks like

                            Doors = {Door1,Door2,Door3,Door4}
                            Offsets = {100,0,0,100,100,0,0,100}

                            The offsets are organized as {Door1ForwardOffset,Door1RightOffset,Door2ForwardOffset,Door2RightOffset...}

                            So if I randomly pick a door 0-3 (lets say the result was "2"), I go to Doors[2] and get Door3
                            Then I use the random index of 2, multiply it by 2 to get the Door3ForwardOffset and add one to get the Door3RightOffset.

                            I did it in this way so that rooms with more than 4 doors could still use the same functions. I suppose I could have had two arrays for offsets, one for Forward and one for Right, but whatever.

                            After that, I don't need any condition check. I do

                            World Location of DoorA + (DoorAForwardVector * Door3ForwardOffset) + (DoorARightVector * Door3RightOffset)

                            So yeah, I guess it's not technically hardcoded, but having each room have an array defining the appropriate offset to use for when a specific door is selected feels like hardcoding/cheating.
                            Last edited by Chumble; 11-05-2014, 04:02 PM.

                            Comment


                              #15
                              I was thinking about one array for each variable (so 3 arrays only) and one entry in each array by room. This is quite the same on the other way but the advantage is that you just have to know your room number to get infos in your arrays. You may create another array with meshes and then when you select room 1 you spawn mesh 1 and use all the 1 entries of all your arrays to set its location. Would be better for you ? In hope...

                              Comment

                              Working...
                              X