node.setTexPos(anothernode.getPos()) ?

I think the title explains my question well enough.
I need to move a texture’s UV based on another node’s position with a task. Kinda like a projected texture without projecting it.

node.setTexPos(textureStage.getDefault(), anothernode.getPos())

will work, but the units are different. How to convert the other nodepath’s position to the texture’s UV position properly?

It sounds like you might be asking for the setTexProjector() call as described at the top of Projected Textures, which updates the UV’s from the other node’s position without doing a full lens-based projection.

David

That acts weird.
What is the third argument for setTexProjector for? Isnt “toNodePath” the “nodePath” itself?

setTexProjector() computes the relative transform between the source NodePath and the target NodePath, and applies that as a relative transform to your texture coordinates.

Thus, when you setPos() the target NodePath, it has the result of an equivalent setTexPos() on your source NodePath.

David

Still seems wrong.
The source is the camera, might that be the issue? I still use base.enableMouse() controls, not directly call base.camera.setPos(). It also seems that texProjector ignores previous calls like setTexScale, huh? Seems like it

mynode.setTexProjector(myts, base.camera, mynode)

I also used this on the texture, might this be a problem?

mytex.setWrapU(Texture.WMClamp)
mytex.setWrapV(Texture.WMClamp)

I think setTexPorjector needs to be in a task, but Ive tried both ways.

If the first parameter to setTexProjector() is a Camera or LensNode, then it will also apply the perspective transform from the lens. If you want to project from the camera’s position without using the lens attributes too, then use base.camera instead of base.cam.

You don’t need to apply setTexProjector() in a task, once is sufficient. But it’s roughly equivalent to creating a task that does something like node.setTexTransform(from.getTransform(to)) every frame.

It will replace a previous transform you’ve established. If you want to apply an additional transform, then you can apply it to a lower node, e.g. use node.setTexTransform() on a parent node, then child.setTexScale() or whatever.

David

Its not working and messes up the texture UVs.
Im using setCombineRgb(), might that cause a problem?

Neither setCombineRgb() nor setWrapU()/setWrapV() have anything to do with UV placement.

Perhaps it is working, but not in a way you expect. Can you clarify precisely what behavior you are expecting to find? If nothing else, you should be able to write a task to perform the precise operation you wish each frame.

David

Again, is this right?

mynode.setTexProjector(myts, base.camera, mynode)

is the “toNodepath” the same as “nodePath” in the manual page?

I used to do somethign like this in a task, but it wasnt accurate, just for testing:

mynode.setTexPos(myts, -base.camera.getX()/150, -base.camera.getY()/150, 0)

I can’t tell you if it’s “right” because I don’t know precisely what you want to achieve. The above setTexProjector() call will apply the relative transform from base.camera to mynode to the texture coordinates of mynode each frame. That’s kind of a weird thing to do, but I don’t know what effect you’re trying to achieve, so I can’t tell you whether this is the way to achieve that or not.

setTexProjector() involves three NodePaths:

a.setTexProjector(ts, b, c)

It’s legal for b or c to be the same as a, but it’s not required. The operation of setTexProjector is to apply the relative transform of b to c to the texture coordinates of a. It’s the same as writing a task that does this each frame:

a.setTexTransform(ts, b.getTransform(c))

Your setTexPos() task will result in a similar effect, but again I can’t tell you whether it will be the effect you want or not, without having an understanding of precisely what effect you want.

David

I think I can explain my case in a simple way. Imagine the camera is really a node, the “mynode” is the ground and I want to project fake shadows based on “nodes” x, y position on “mynode” (the ground).

You mean you want to put a shadow on “mynode” that happens to be below “node”? Using setTexProjector(), or setTexTransform(), is only part of the solution. The rest of it is to do mynode.setTexGen(ts, TexGenAttrib.MWorldPosition), so that the texture coordinates you’re transforming are in the right space to begin with.

Or, you can just use mynode.projectTexture(), which does this sort of thing for you automatically, as described in the manual.

But your OP says you don’t want to use a projected texture, and yet what you describe is exactly what a projected texture is, so I still don’t understand what it is you do and don’t want to happen.

David

This sample uses texture projection, it may help:
[Shaderless Shadows)

Its not really a shadow, but thanks anyway. BTW, too bad that menthod doesnt work with shader generator.

This is all there is to it:

This doesnt work:

plane.setTexProjector(myts, ball, plane)

nor this in a task:

plane.setTexTransform(myts, ball.getTransform(plane))

Are you saying I need

plane.setTexGen(myts, TexGenAttrib.MWorldPosition)

for this to work? Is this what converts the camera/ball/etc world units to texture’s UV units?
It looks pretty strange, it seems to take into account the camera angle, not position in that case.
And I think projectTexture() wouldnt work only because I only need to use the node’s x and y position.

Again this works, but its hacky approach:

mynode.setTexPos(myts, -base.camera.getX()/150, -base.camera.getY()/150, 0)

I mean dividing the values by 150. I just do that because Im not sure hoe the uv x,y sizes differ with a node’s one and how to convert from one to another.

Projected textures can be used to implement shadows, but they aren’t exclusively used for shadows. What you’re describing is a projected texture.

The reason that you need to do the setTexGen() call is because your UV’s don’t initially correspond to XYZ position, so the setTexTransform() call doesn’t make sense. In your case, though, it appears that your UV’s almost correspond to XYZ position, with the exception of a scale by 150, so doing the counterscale explicitly mostly works for you. So you can just do that if it makes more sense to you.

David

That value isnt 100% correct, it gets worse as yuo move farther.
Id like it to be 100% correct by doing that setTexGen you suggested, but like I said it seems to use the camera’s anles, not position. I could try it with a non camera node to see if something changes.

Just use it with a node that doesn’t rotate. If you need the ball to rotate, then make it a child of the node that has the ball’s position, and rotate only the ball itself.

David

Oh, I guess.
In that case it seems to go on the opposite x, y direction. plus the offset of the texture is wrong.

Perhaps you have the order of the parameters wrong in setTexProjector(). Or just use nodePath.projectTexture(), which generally gets the order right.

David

cameranode = render.attachNewNode('cameranode')

def textureTask(task):
	cameranode.setX(base.camera.getX())
	cameranode.setY(base.camera.getY())
	
	plane.setTexTransform(myts, cameralnode.getTransform(plane))
	plane.setTexGen(myts, TexGenAttrib.MWorldPosition)
	
	return task.cont

taskMgr.add(textureTask, "textureTask")

or

cameranode = render.attachNewNode('cameranode')

def textureTask(task):
	cameranode.setX(base.camera.getX())
	cameranode.setY(base.camera.getY())
	
	return task.cont

taskMgr.add(textureTask, "textureTask")

plane.setTexProjector(myts, cameranode, plane)