mesh transform problem
Blitz3D Forums/Blitz3D Programming/mesh transform problem
| ||
Hi lads, Given two 3D coordinates in world space, how can we stretch a quad between them retaining thickness and yet rotate the points of the quad in such a way that it doesn't backface at any time, nor lose it's retangular form. I am deforming the verts of a single surface quad to stretch between two pivots. A bit like a lightsaber effect. It has to be done by mesh vert manipulation. As you know, it has to avoid backface culling. EntityFx 16 is just a waste we can avoid here. I believe TformVector or point can help me achieve this goal. Any help/tips you can give will be appreciated lads! |
| ||
Hmmm... trying to visualize this: The 'front' of a triangle is relative to the camera. So the first step must to be to transform everything to camera space. How about this. Use another pivot in the same location as the camera. Aim it at one of the two target pivots. Now rotate this 'camera pivot' around it's z-axis until the two targets are on a horizontal line in camera pivot space. They will both have y-coordinates equal to zero. As seen from the camera pivot the targets are in front, on the same y level. The four corners of a stretched quad would be slightly above and below the targets. i.e. just add or subtract a little from the target y-coordinates (in camera pivot space). Transform the results back into quad space and you are done. You need to fill in some details here. But the idea sounds right. |
| ||
Here's a demo of the tricky part, rotating by the right amount. It actually turns the camera rather than a 'camera pivot' so we can see the results. ; Tap a key to step through demo. Escape quits. ; 1. random positions ; 2. aim at red ; 3. turn so green is to the right Graphics3D 640, 480, 32, 1 p1 = CreateSphere() : EntityColor p1, 255,0,0 p2 = CreateSphere() : EntityColor p2, 0,255,0 cam = CreateCamera() Repeat PositionEntity p1, Rnd(-4,4), Rnd(-4,4), 10 + Rnd(0,5) PositionEntity p2, Rnd(-4,4), Rnd(-4,4), 10 + Rnd(0,5) RenderWorld : Flip : WaitKey ; random PointEntity cam, p1 RenderWorld : Flip : WaitKey ; aim at red TFormPoint EntityX(p2,True), EntityY(p2,True), EntityZ(p2,True), 0, cam angle# = ATan2( TFormedY(), TFormedX() ) TurnEntity cam, 0, 0, angle ; After this we are aiming at red sphere RenderWorld : Flip : WaitKey ; with green sphere to the right. Until KeyHit(1) |
| ||
Thanks for the help! Still a bit confused though. What do you mean by transforming back? Not sure how to in order to get a useful result... transform the camerapivot... |
| ||
Basically trying to make a useful line using quads without skewing, and retaining thickness. |
| ||
problem - given p0,p1 two pivots in 3space calculate e0,e1 vectors that represent the end edges of a quad streteched between p0,p1 facing camera so 4 verts of quad in global space are positioned at p0+e0,p1+e1,p1-e1,p0-e0 solution - the vector e0 needs to be at a tangent to the vector p1-p0 and the vector camera-p0 (similarly e1 is normal to p0-p1 cam-p1) so won't that just involve a single cross product for each end? |
| ||
Thanks for that skid, it seems logical although I haven't a single clue how to do it. But here's hoping I'll blunder my way to success. |
| ||
Just experimenting now, been meaning to have a hack at this for some time... |
| ||
Haven't tested with moving camera so may not be quite there yet. A lot of stuff in UpdateWireMesh could be precalculated in wire type if wires are not too dynamic.; wired.bb ; 3d wire frame system ; wires are lines in 3D space with start and end widths ; CreateWireMesh creates single surface mesh with quad per wire ; UpdateWireMesh positions wire quad so as to face the camera Type wire Field x0#,y0#,z0#,w0# Field x1#,y1#,z1#,w1# End Type Function CreateWire.wire(x0#,y0#,z0#,w0#,x1#,y1#,z1#,w1#) w.wire=New wire w\x0=x0 w\y0=y0 w\z0=z0 w\w0=w0 w\x1=x1 w\y1=y1 w\z1=z1 w\w1=w1 End Function Function CreateWireMesh() m=CreateMesh() EntityFX m,16 ;double sided flag so no tricky flip testing required s=CreateSurface(m,b) For w.wire=Each wire AddVertex s,0,0,0,0,0 AddVertex s,0,0,0,1,0 AddVertex s,0,0,0,1,1 AddVertex s,0,0,0,0,1 AddTriangle s,v+0,v+1,v+2 AddTriangle s,v+0,v+2,v+3 v=v+4 Next Return m End Function Function UpdateWireMesh(cam,mesh) s=GetSurface(mesh,1) camx#=EntityX(cam) camy#=EntityY(cam) camz#=EntityZ(cam) For w.wire=Each wire px#=w\x1-w\x0 py#=w\y1-w\y0 pz#=w\z1-w\z0 l#=1.0/Sqr(px*px+py*py+pz*pz) px=px*l py=py*l pz=pz*l cx#=w\x0-camx cy#=w\y0-camy cz#=w\z0-camz l#=1.0/Sqr(cx*cx+cy*cy+cz*cz) cx=cx*l cy=cy*l cz=cz*l l=w\w0 ex#=l*(py*cz-pz*cy) ey#=l*(-px*cz+pz*cx) ez#=l*(py*cx+px*cy) VertexCoords s,v+0,w\x0+ex,w\y0+ey,w\z0+ez VertexCoords s,v+3,w\x0-ex,w\y0-ey,w\z0-ez cx#=w\x1-camx cy#=w\y1-camy cz#=w\z1-camz l#=1.0/Sqr(cx*cx+cy*cy+cz*cz) cx=cx*l cy=cy*l cz=cz*l l=w\w1 ex=l*(py*cz-pz*cy) ey=l*(-px*cz+pz*cx) ez=l*(py*cx+px*cy) VertexCoords s,v+1,w\x1+ex,w\y1+ey,w\z1+ez VertexCoords s,v+2,w\x1-ex,w\y1-ey,w\z1-ez v=v+4 Next End Function Graphics3D 1024,768 ; front square CreateWire(-100,100,200,1, 100,100,200,1) CreateWire(-100,-100,200,1, 100,-100,200,1) CreateWire(-100,-100,200,1, -100,100,200,1) CreateWire(100,100,200,1, 100,-100,200,1) ; side lines CreateWire(-100,-100,200,1, -100,-100,-200,1) CreateWire(100,-100,200,1, 100,-100,-200,1) CreateWire(100,100,200,1, 100,100,-200,1) CreateWire(-100,100,200,1, -100,100,-200,1) ; back square CreateWire(-100,100,-200,1, 100,100,-200,1) CreateWire(-100,-100,-200,1, 100,-100,-200,1) CreateWire(-100,-100,-200,1, -100,100,-200,1) CreateWire(100,100,-200,1, 100,-100,-200,1) mesh=CreateWireMesh() cam=CreateCamera() While Not KeyHit(1) TurnEntity cam,0,1,.3 UpdateWireMesh(cam,mesh) UpdateWorld RenderWorld Flip Wend End |
| ||
and try adding this after the CreateWireMesh for antialiased lines (need to double the end widths for best effect):tube=CreateTexture(1,4,4) brush=CreateBrush() BrushTexture brush,tube t=TextureBuffer(tube) WritePixel 0,0,0,t WritePixel 0,1,-1,t WritePixel 0,2,-1,t WritePixel 0,3,0,t PaintMesh mesh,brush |
| ||
Thats the business simon! There are issues when you look outside the wireframe box though. It's pretty awesome having aa wireframes! Any chance of doing a bit more work on this for us? it's a god send for all aspiring tron programmers! |
| ||
The resulting width is a little varied so will hopefully come up with better maths soon. |
| ||
I may be missing the point a bit but why not just transform the 3D coords into 2D then draw wires with a 2D in 3D solution? Each line could be just stretched 2D quad facing the camera (perhaps in orthographic mode) and you'll get perfect fixed width wires. Use a nice alpha mapped texture and you can get a nice glow on the lines. |
| ||
I like that solution but we lose z, meaning the wires are always visible - even behind other objects. At the moment, I can put an original source object inside the wire cage if I want. |
| ||
Fairy Nuff |
| ||
*sneaky pointless bump* |