Hiya!
If you already HAVE the h/v then its fairly easy:
------------------------------------------------------------
--ghSetColorAt3DCollision
------------------------------------------------------------
--Purpose: takes information from a raytrace collision and
--returns the color of the texture of the pixel at that
--point on the object (reverse texture lookup)
------------------------------------------------------------
on ghSetColorAt3DCollision a_vHitPosition, a_aTriangle, \
a_aTexCoords, a_mModel, a_rgbColor
--get texture from this model
sTexName = a_mModel.shader.texture.name
--should worry about whether this image exists in cast...
imgTexImg = member(sTexName).image
fX = ((imgTexImg.width-1) * a_aTexCoord[1])
fY = imgTexImg.width - (((imgTexImg.width-1) * a_aTexCoord[2]))
--setColor out of image and return
imgTexImg.setPixel(fX, fY, a_rgbColor)
a_mModel.shader.texture.image = imgTexImg
updatestage
end ghGetColorFrom3DCollision
------------------------------------------------------------
If you DON'T already have the h/v, and only have position, and don't want to
blindly use the h/v from modelsUnderRay, then it's a little harder:
(Pasting this bit from a private conversation)
[someone] is right - it is "barycentric something". More specifically, it is
barycentric co-ordinates, which define a point as a point relative to the 3
vertices of a triangle. More correct still, it is a vector (which may or may
not be normalized but whose
sum = 1) . You can normalize barycentric coordinates such that the vector's
elements represent the normalized area of the three smaller triangles created
inside the larger one by drawing a line from the point to each of the 3
vertices. For the geek
crowd, it is generally believed that barycentric coordiantes were discovered by
Mobius in 1827.
so AS I WAS SAYING...
The problem [someone] was having is that several methods for finding
barycentric coordinates depend on the winding order of the triangle - so for
backfacing triangles and/or every other triangle in a mesh, they will be
backwards. That is no fun, so here is a
method that works the same regardless of winding order:
--code based on discussion by David Watson, on comp.graphics
--b0 = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1)
--b1 = ((x2 - x0) * (y3 - y0) - (x3 - x0) * (y2 - y0)) / b0
--b2 = ((x3 - x0) * (y1 - y0) - (x1 - x0) * (y3 - y0)) / b0
--b3 = ((x1 - x0) * (y2 - y0) - (x2 - x0) * (y1 - y0)) / b0
--baryC = vector(b1, b2, b3)
(interesting side note, if all components of the vector are > 0 then P is
guaranteed to be within the triangle)
unfortunately, you all want to go from 3D into 2D, and not 2D into 3D (which is
what I was doing with the above) so I had to work up another method for y'all.
When you fire a modelsUnderRay or modelsUnderLoc you generally get a structure
back that looks something like this:
-- [[#model: model("Plane2"), #distance: 206.7631, #isectPosition: vector(
-150.0000, 111.7515, 149.9010 ), #isectNormal: vector( 1.0000, 0.0000, 0.0000
), #meshID: 1, #faceID: 2, #vertices: [vector( -150.0000, 250.0000, -150.0000
), vector( -150.0000,
250.0000, 150.0000 ), vector( -150.0000, -50.0000, 150.0000 )], #uvCoord: [#u:
0.5388, #V: 0.4608]]]
Note two things: the #isectPosition, and the #vertices array.
This means that we have a point on that triangle (#isectPosition) that I will
now refer to as P. We also have the 3 points that make up the points that form
the triangle that we think we struck. So we can produce a vector that
represents P in
barycentric form. Like this:
on mCompute3DBarycentricCoordinates me, V0, V1, V2, P
--triangle ABC, points are V0, V1, V2
--along with a point, P (inside it, and planar, plz)
u = V1 - V0
v = V2 - V0
w = P - V0
d = (power(u.dot(v), 2) - (u.dot(u))*(v.dot(v))) --denominator
s = ((u.dot(v))*(w.dot(v)) - (v.dot(v))*(w.dot(u))) / d
t = ((u.dot(v))*(w.dot(u)) - (u.dot(u))*(w.dot(v))) / d
w = s*u + t*v --unique if P lies within the plane of ABC
b0 = (1-s-t)
b1 = s
b2 = t
me.vBaryC = vector(b0, b1, b2)
end mCompute3DBarycentricCoordinates
Wasn't that cool? Ugggh... many many nights figuring that stupid thing out,
very frustrating. You will find that you need to *negate the Y component* of
the vertices of the triangle (V0, V1, V2) in order to get the texture mapping
correct. Why? Well...
because. That's all I will say about that until I write the paper, because I'm
honestly not sure exactly what Director is doing under the hood that it is
necessary, other than that it works. An oddity. Also please note, that I am
feeding that handler
the positions of the point, and the vertices in WORLD SPACE. This is the way
that they usually come back from the modelsUnderRay command, but its important
to note since giving it one in model space and one in world space will really
mess it up.
So now that we have that vector, we can think of those Barycentric coordinates
as *weights* that describe the position of P relative to the 3 points of the
triangle. The magic is that these weights are the EXACT SAME in 2D as in 3D. We
already know
(hopefully from a #meshDeform or a #mesh modelResource, and by using the
#meshID and #faceID returned) that the 3 points of the face we hit maps to a
tuple of UVs, such that V0 -> UV0, V1 -> UV1, V2 -> UV2. So we can find the
exact UV for point P
relative to the 3 UVs that represent the points of the triangle. Like this:
on mFindTexelBaryway me, UV0, UV1, UV2
TexCoord = [] --initialize
TexCoord[1] = ( me.p_vBaryC[1] * UV0.x ) + ( me.p_vBaryC[2] * UV1.x ) + (
me.p_vBaryC[3] * UV2.x)
TexCoord[2] = ( me.p_vBaryC[1] * UV0.y ) + ( me.p_vBaryC[2] * UV1.y ) + (
me.p_vBaryC[3] * UV2.y)
return TexCoord
end mFindTexelBaryway
Neat! I was so stunned when I got this to work, it was seriously like good
old-fashioned voodoo. But I can hear you saying 'Why do I want to do all this
rather than just use the #uvCoord that is returned when I smack into an
object...' Well, it
depends. Since you are feeding it the 3 UVs associated with the triangle it
hit, you DON'T have to worry about how the texture is mapped; since the
texCoords you retrieve from the mesh are the ones that exist when it is already
projected! And, since
you can get the texture coords from any given texture layer, you can have
different textures mapped to different layers (with different mapping
modifiers) and get the (distinct) texture coords for P at any of the different
layers by a new call to
mFindTexelBaryway.
Is it useful? I'm not totally sure. I used a modification of this as the basis
for the lightmapper I am working on (I actually go the other way, compute the
barycentric coords in 2D from texture space and map it to an estimated 3D world
position) to
'pre-bake' shadows and other rendering artifacts into textures as the movie
starts up. ( See the screenie!!
http://andysgi.rit.edu/andyworld10/tests/lightmapper1.jpg )
I hope that it proves useful to you, in your painting applications, but I
haven't tested it as such, so I don't know if it will meet your needs. If you
do wind up using it for something really cool I'd appreciate it if you could
drop me a line and say
'look at the cool thing that incporates that wierd email you wrote to that list
we can't talk about'. That would make me very happy.
Hope this helps!
-Andy
RIT
Andrew Phelps
Assistant Professor
Department of Information Technology
College of Computing and Information Sciences
Rochester Institute of Technology
http://andysgi.rit.edu [EMAIL PROTECTED]
-----Original Message-----
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Luiz Gustavo
Castelan P�voas
Sent: Monday, January 31, 2005 7:34 AM
To: Lingo programming discussion list
Subject: <lingo-l> xy position of a texture
Hello list
I am trying to get the x,y position of the texture applyed to a surface using
modelUnderLoc,
so, when I click the model, the texture under that mouseloc position gets
'painted' on the 3d object.
Is it possible with director (I gess so!), how do I get the UV TEXTURE
position? (instead of UV face
coordinate).
thanks
Luiz
PS: urgent
[To remove yourself from this list, or to change to digest mode, go to
http://www.penworks.com/lingo-l.cgi To post messages to the list, email
[email protected] (Problems, email [EMAIL PROTECTED]). Lingo-L is for
learning and helping with programming Lingo. Thanks!]
[To remove yourself from this list, or to change to digest mode, go to
http://www.penworks.com/lingo-l.cgi To post messages to the list, email
[email protected] (Problems, email [EMAIL PROTECTED]). Lingo-L is for
learning and helping with programming Lingo. Thanks!]