point two axis

I know that I can point a model’s y axis at a certain point, but how would I find a rotation such that its y axis is pointing at one point and its z axis is pointing at another, provided that the two vectors from the model to the points are at right angles to each other?

Hmm… Have you tried the “headsUp” method? Judging by the description, it may do what you want. There also seems to be a version of “lookAt” that takes an “up” vector; I don’t know what the difference is, offhand.

That function seems perfect for my needs, but I wrote some code that was designed to make a rhombic tricontahedron with a coordinate space for each face so that the z axis was perpendicular to the face and the vertices of the face lied on the x and y axises.(axi?)

My method, since a rhombic tricontahedron is basically a dodecahedron( or icosahedron)with its edges switched with faces, is to take a list of dodecahedron vertices and edges, calculate the midpoint of each edge, make a coordinate system to go at each point, and point the y axis at one of it’s dodecahedral vertices, and its z axis along the vector from the center to the midpoint.

But each face seems to be rotated a little ‘off’, and four faces are rotated 90 degrees from where they should be. Am I using the function wrong?

		self.planet = render.attachNewNode("planet") #the base node for convenience
		csys = [self.planet.attachNewNode("coordsystem") for null in xrange(30)] #the coordinate spaces for each face
		fundem = [] #list of vertecies
		edgeind = [] #list of indecies for edges
		s = 2.0 / (1 + sqrt(5)) #1/phi
		t = (1 + sqrt(5)) / 2.0 #phi
		for z in (-1,1):
			for y in (-1,1):
				for x in (-1,1):
					fundem.append((x,y,z))
		for u in (-1,1):
			for v in (-1,1):
				fundem.append(( (s*u),(t*v),0     ))
				fundem.append(( 0    ,(s*u),(t*v) ))
				fundem.append(( (t*v),0    ,(s*u) )) #this whole section generates vertecies
		edgeind.append((8,14))
		edgeind.append((11,17))
		edgeind.append((9,15))
		edgeind.append((12,18))
		edgeind.append((10,16))
		edgeind.append((13,19))
		edgeind.append((8,0))
		edgeind.append((8,4))
		edgeind.append((14,1))
		edgeind.append((14,5))
		edgeind.append((11,2))
		edgeind.append((11,6))
		edgeind.append((17,3))
		edgeind.append((17,7))
		edgeind.append((9,0))
		edgeind.append((9,1))
		edgeind.append((15,2))
		edgeind.append((15,3))
		edgeind.append((12,4))
		edgeind.append((12,5))
		edgeind.append((18,6))
		edgeind.append((18,7))
		edgeind.append((10,0))
		edgeind.append((10,2))
		edgeind.append((13,1))
		edgeind.append((13,3))
		edgeind.append((16,4))
		edgeind.append((16,6))
		edgeind.append((19,5))
		edgeind.append((19,7))#put edges in the list
		for i,edge in enumerate(edgeind):
			cent = ((fundem[edge[0]][0]+fundem[edge[1]][0])/2.0,
			        (fundem[edge[0]][1]+fundem[edge[1]][1])/2.0,
			        (fundem[edge[0]][2]+fundem[edge[1]][2])/2.0) #calculate vector from center to midpoint of edge
			csys[i].setPos(cent) #set position of coordinate system
			csys[i].headsUp(other = self.planet,point=fundem[edge[0]],up=cent) #orient it such that it is pointing towords one vertex and up is away from the center.
		vdata    = GeomVertexData('pregentiles', GeomVertexFormat.getV3c4(), Geom.UHStatic) #debugging model showing where dodahedral vertecies are and midpoints of edges are
		prim     = GeomPoints(Geom.UHStatic)
		vertex   = GeomVertexWriter(vdata, 'vertex')
		color    = GeomVertexWriter(vdata, 'color')
		curind = 0
		for vert in fundem:#add dodecahedral vertecies into the thing
			vertex.addData3f(vert)
			color.addData4f(0,1,0,1)
			prim.addVertex(curind)
			curind+=1
		for coord in csys: #add midpoints into the thing
			vertex.addData3f(self.planet.getRelativePoint(coord,(0,0,0)))
			color.addData4f(1,1,0,1)
			prim.addVertex(curind)
			curind += 1
		geom = Geom(vdata)
		geom.addPrimitive(prim)
		node = GeomNode('pregentiles')
		node.addGeom(geom)
		self.planet.attachNewNode(node).setRenderModeThickness(12)
		for duprup in csys: #put rhombus model in each coordinate system
			tao = t/2
			verts = [(0,tao,0),(.5,0,0),(-.5,0,0),(0,-tao,0)]
			vdata = GeomVertexData('sphere',GeomVertexFormat.getV3n3c4(),Geom.UHStatic)
			vdata.setNumRows(len(verts))
			vertex = GeomVertexWriter(vdata, 'vertex')
			normal = GeomVertexWriter(vdata, 'normal')
			color = GeomVertexWriter(vdata, 'color')
			prim = GeomTriangles(Geom.UHStatic)
			for vert in verts:
				vertex.addData3f(vert[1],vert[0],vert[2])
				normal.addData3f(vert[1],vert[0],vert[2])
				color.addData4f(1,0,0,1)
			prim.addVertices(1,2,0)
			prim.addVertices(1,3,2)
			geom = Geom(vdata)
			geom.addPrimitive(prim)
			node = GeomNode('gnode')
			node.addGeom(geom)
			nodePath = duprup.attachNewNode(node)
			nodePath.setRenderModeWireframe(True)

The proper plural is “axes” (pronounced more or less as “ax-ees”), I believe. :slight_smile:

Ah, wow. Hum… I’m a little tired, so I haven’t read through that code and the following may well be wrong, but it may at least be a start:

Rotate the relevant NodePath such that one of its axes lined up with the intended vector (by finding the angle between the vectors, then using the cross-product to find the angle around which to rotate, and using those to construct a quaternion rotation which you then apply), then find the angle between the other axis and its intended vector and perform a relative rotation using that value.