well at least it’s not just me. it really SEEMS like it’s an easy thing to do…like just “connectTo”
i had considered a fix mapping for each connection (though, connections are user defined, but i know its rotation relative to the front face, or in world coordinates) thing is, what rotation i need to make is a function of which connection i’m connecting TO and which connection i’m connecting FROM. in 2d this would probably not be a hard problem, but in 3d…well…rotations are weird in 3d.
i thought maybe quaternions could help me, just made me thing: “you had a problem, so you thought you would use quaternions, now you have two problems”
cus if rotations in three dimensions were cooking your noodle, let’s bring it to 4 dimensions.
been thinking maybe matrices could help…but i have no idea what is going on there.
i can work out the orientation in local space for the object being connected to (basically start.angleTo(end)*(dirToZero.x+dirToZero.y+dirToZero.z)(unless the angle is 0 and the multiple is -1, then it’s 180) as its rotation along the local z axis, and 90 degrees as its rotation along the axis the line moves (x or y or some combination of both)
so, that top line, as an example, moves along its local x axis, its rotation along the front face is 0, a part connecting to it would have a rotation, in that objects local space, of 90,0,0
one on the right side however would have a rotation of 0,90,90, this is because it has a 90 degree rotation about the z axis, and a 90 degree rotation about the y axis (the axis along which the line is drawn) while the left side would be 0,90,-90
i can even get this orientation in the world space too, its 2d rotation is always about its normal and the 90 degree is along the axis the line moves. but i haven’t the foggiest how to turn the other parts rotation into that rotation
position is easy enough, the positioning works just fine (i just set the position of the connecting part to the centre of the connection line and then back if off along the other parts normal by the distance from the centre of the part to the centre of the connection line of that part (or, i will when i figure out how to handle 45 degree angles, right now i just use the height/2 or width/2 as need be))
right now my rotation method is
this.setRotation(new THREE.Euler(0,0,0));//first clear out the rotation
var first=connection.owner.obj.localToWorld(connection.line.geometry.vertices[1].clone()).sub(connection.owner.obj.localToWorld(connection.line.geometry.vertices[0].clone()));//this is the distance and direction of the oher line
var second=ownConnection.owner.obj.localToWorld(ownConnection.line.geometry.vertices[1].clone()).sub(ownConnection.owner.obj.localToWorld(ownConnection.line.geometry.vertices[0].clone()));//this is the distance and direction of my line
var axis=cleanVector(first.clone().normalize());//this is just the direction of the other line
var axis2=cleanVector(second.clone().normalize());//and this is just the direction of my line
var rotAxes=cleanVector(axis.clone().cross(axis2).normalize());//now we want to know what axis to rotate these about, if a rotation is needed, taking the cross product of their vectors gives a vector orthagonal to both, that's the one i want to rotate about.
rotAxes.multiply(rotAxes);//here i multiply it by itself to insure it's positive, being positive or negative here is accidental based on the order they did the lines in, so i don't want to depend on that
var theta=first.angleTo(second);//so this is just the angle between the two connections
this.rotateOnWorldAxis(rotAxes,theta);//now let's rotate it by that angle on the axes we determined above.
var firstConnectionNormal=connection.owner.obj.localToWorld(new THREE.Vector3(0,0,-1)).sub(connection.owner.obj.localToWorld(new THREE.Vector3(0,0,0)));//this is the normal of the connecting object, that is a vector orthagonal to the plane that is the face of the part
cleanVector(firstConnectionNormal);//because floating points...
var [dirFromZero,norm2]=getDirFromZero(connection);//this gets the direction from the 0 point to the line and also gives the direction of the line this one is for the other connection
var [myDirFromZero,myNorm]=getDirFromZero(ownConnection);//this one is for my connection
var testVec=this.obj.localToWorld(new THREE.Vector3(myDirFromZero.x,myDirFromZero.y,0)).sub(this.obj.localToWorld(new THREE.Vector3(0,0,0)));//this is myDirFromZero but with world coordinates
var theta=firstConnectionNormal.angleTo(testVec);//this will get the angle between the world vector pointing from the 0 point of my object to my connecting line and the vector which is the normal of the object i'm connecting to
this.rotateOnAxis(new THREE.Vector3(-1,0,0),theta);//and rotate it here, the vector will always be the local x so i use that fact
var norm=ownConnection.owner.obj.localToWorld(new THREE.Vector3(0,0,-1)).sub(ownConnection.owner.obj.localToWorld(new THREE.Vector3(0,0,0)));//this one is my norm, like firstConnectionNormal but for my object
var positiveNorm=norm.clone().multiply(norm);//this is the positive of that normal
var _dir=ownConnection.owner.obj.localToWorld(new THREE.Vector3(0,0,0)).multiply(positiveNorm).normalize();//i think this migh be redudntant, think it's always the same as positiveNorm
var translationVector=_dir.multiplyScalar(this.material.base.thickness/2);//so taking the dir vector and multiplying it by material thickness/2 will apply it only to that direction.
dirFromZero.multiplyScalar(-1);//turn dirToZero into dirFromZero
[myDirFromZero,myNorm]=getDirFromZero(ownConnection);
var firstConnectionDirFromZero=connection.owner.obj.localToWorld(new THREE.Vector3(dirFromZero.x,dirFromZero.y,0)).sub(connection.owner.obj.localToWorld(new THREE.Vector3(0,0,0)));//this is dirFromZero for other connection in world coordinates
var myOrthoNorm=this.obj.localToWorld(new THREE.Vector3(0,0,-1)).sub(this.obj.localToWorld(new THREE.Vector3(0,0,0)));//this is the same as the code for norm, but i need to get it again since there as been a change to world coordinates since then.
var flip=myOrthoNorm.clone().add(firstConnectionDirFromZero).length()*(Math.PI/2);//if my normal is going in the same direction as the vector from the origin of the other object to the connection line then i need to flip 180 degrees, if they are in opposite directions all is well.
this.rotateOnWorldAxis(firstConnectionNormal,flip);//listen to my story all about how my object got flip turned upside down.
like i said, it’s a bit of a mess, sometimes that local x rotation is inappropriate (this works for any first connection, problem happens when i try and make a second connection that is orthagonal to the first, i flip along the normal of the other part, this can cause the connection on the first part to be at the opposite end, my current workaround is to only do the first order connection and just add the other connections, but ideally there should be some simple transformation i can do where no matter which part i’m doing the connection from they all agree on the orientation (if i connect to one on the left that’s going along the y it should give the same rotation as one on the top going along the x)
adding it as a child MIGHT be possible, i’d have to register an event for when the rotation changes to update the rotation in the container object (currently it handles that when you tell the container to rotate, but if its a child of another part, when that part rotates it will change the rotation of this part, presumably it fires an event when that happens)