Need alignment math help!
Blitz3D Forums/Blitz3D Programming/Need alignment math help!
| ||
Okay, here goes.. Sprites face to the camera nicely usually but if I parent sprite to object that moves and spins then sprite does not seem to do that. Goal is to make sprites one(two) axis to be in line with object whic is its parent and still turn its face to camera like sprites usually do (like trees in Castle.bb example..) here is mockup for result I want: ![]() In .bb example below sprite sits nicely to its parent end but rolls all too wrong.. |
| ||
Do you want to make the sprite smaller when viewed from the back ? Maybe you could use a few round sprites in a row with a descending alpha ? |
| ||
I'm on it. |
| ||
HandleSprite is the culprit. Try this: |
| ||
bram32: thats the usual way to do that but not the way I want :) Chroma: It did not seem to fix it.. when using "SpriteViewMode sp,4" (which i want to use :) ) it does not matter which command to position sprite, HandleSprite or PositionEntity. Exhaust sprite still rolls with the tube. AlignToVector should make this work but it is bit hazy to me how calc suitable vector.. I know that one alignment vector from sprite should cross camera Z axis.. and still sprites other two axis should be same as tubes.. so rolling is only thing I want to adjust. |
| ||
Finjogi, You simply can't use a sprite entity in this situation. In order to align it the way you're looking for you'd need to use a quad and continuously update the vertices relative to the camera. Also, you'd need to use different textures depending on it's angle to the camera. TBH, I think you're over-complicating this and should just use a mesh ... once textured it'll look much better than some overcomplex aligned quad. I guess that's not what you want but I'll leave an example of what I mean. Stevie Graphics3D 640,480,32,2 light = CreateLight() cam = CreateCamera() PositionEntity cam, 0, 0, -10 tube = CreateCylinder( 12,True ) RotateMesh tube, 90, 0, 0 FitMesh tube, -1,-1,-2,2,2,2 EntityColor tube, 128,128,128 flame = CreateCone( 12, False, tube ) RotateMesh flame, 90, 0, 0 FitMesh flame, -1,-1,0,2,2,1 EntityAlpha flame, .25 EntityColor flame, 250,150,50 While Not KeyDown(1) TurnEntity tube,1,1,1 ScaleEntity flame, 1, 1, Rnd( .5, 10 ) RenderWorld Flip True Wend End |
| ||
A=emitter to camera vector B=emitter eject vector -> the direction of the burner C=cross product of those vectors.. -C=opposite of C position top and bottom verts using C, and -C..these should be unit vectors perpendicular to the plane formed by the vectors A and B. These vectors are the up and down positions of the verts, you need to scale them to radius of your burner, and add the burner position - resulting in the first two vertex positions in world space.. the end vertices are simply offsets from these two points, along the emitter vector.. hope that wasnt too hard to follow...there may be easier ways to create cylindrical billboards..but this method works quite well.. |
| ||
Defoc8: Thanks for tips, It did not need to build verts every frame. And yes, like you wrote, cross product was my missing part and so now it works, with sprites :) And here is whole code + sprite images: exhaust.zip |
| ||
Cool! Looks very nice. |
| ||
This looks fantastic. But I have run up against a problem. I've tried importing the effect into my own program, and used it to obtain a laser effect. The problem is that the lasers lie in the vertical direction, not the horizontal direction, and can when I rotate the camera, the sprites are flat when sometimes viewed from the sides. This leads me to believe that i've made a mistake in the alignment, somehow. Any advice? Here's the code. (I've edited it to contain only the essential parts.) graphicsX = 1280 graphicsY = 1024 Graphics3D graphicsX, graphicsY, 32, 1 SetBuffer = BackBuffer() Type laserType Field pivot, sprite, colour$, status$, speed#, damage#, range#, distanceTravelled# Field x#, y#, z#, x2#, y2#, z2#, cx#, cy#, cz#, tx#, ty#, tz#, vx#, vy#, vz# End Type Dim laserArray.laserType(9999) For i = 0 To 9999 laserArray(i) = New laserType laserArray(i)\status = "Dead" Next BlueLaserSprite = LoadSprite("BlueLaser.bmp", 1+8+16+32) While Not KeyDown(1) WaitTimer(frameTimer) ; Fire Player's Primary Weapons If MouseHit(1) Gosub playerPrimaryWeapons EndIf ; Keep Track of all Weapons Gosub Weapons RenderWorld Flip True Wend End .Weapons For i = 0 To 9999 If laserArray(i)\status = "Alive" TranslateEntity laserArray(i)\pivot, -laserArray(i)\speed*Sin(EntityYaw(laserArray(i)\pivot)), -laserArray(i)\speed*Sin(EntityPitch(laserArray(i)\pivot)), laserArray(i)\speed*Cos(EntityYaw(laserArray(i)\pivot)) laserArray(i)\x# = EntityX(laserArray(i)\pivot, True) laserArray(i)\y# = EntityY(laserArray(i)\pivot, True) laserArray(i)\z# = EntityZ(laserArray(i)\pivot, True) laserArray(i)\x2# = EntityX(camera, True) laserArray(i)\y2# = EntityY(camera, True) laserArray(i)\z2# = EntityZ(camera, True) laserArray(i)\cx# = laserArray(i)\x# - laserArray(i)\x2# laserArray(i)\cy# = laserArray(i)\y# - laserArray(i)\y2# laserArray(i)\cz# = laserArray(i)\z# - laserArray(i)\z2# TFormVector 0,0,-1, laserArray(i)\pivot,0 laserArray(i)\tx# = TFormedX() laserArray(i)\ty# = TFormedY() laserArray(i)\tz# = TFormedZ() laserArray(i)\vx# = laserArray(i)\cy# * laserArray(i)\tz# - laserArray(i)\cz# * laserArray(i)\ty# laserArray(i)\vy# = laserArray(i)\cz# * laserArray(i)\tx# - laserArray(i)\cx# * laserArray(i)\tz# laserArray(i)\vz# = laserArray(i)\cx# * laserArray(i)\ty# - laserArray(i)\cy# * laserArray(i)\tx# AlignToVector(laserArray(i)\sprite, laserArray(i)\vx#, laserArray(i)\vy#, laserArray(i)\vz#, 1) AlignToVector(laserArray(i)\sprite, laserArray(i)\tx#, laserArray(i)\ty#, laserArray(i)\tz#, 2) EndIf Next Return .playerPrimaryWeapons i = 0 Repeat If laserArray(i)\status = "Dead" ; Speed and other variables should be set here, determined by what weapon is firing. laserArray(i)\status = "Alive" laserArray(i)\speed = 0.1 laserArray(i)\pivot = CreatePivot() PositionEntity laserArray(i)\pivot, EntityX(masterPivot), EntityY(masterPivot), EntityZ(masterPivot) RotateEntity laserArray(i)\pivot, EntityPitch(playerPivot), EntityYaw(playerPivot), 0 ;Set Up Laser Sprite laserArray(i)\sprite = CopyEntity(BlueLaserSprite) SpriteViewMode laserArray(i)\sprite, 4 ScaleSprite laserArray(i)\sprite, 1, 10 EntityFX laserArray(i)\sprite, 17 EntityParent laserArray(i)\sprite, laserArray(i)\pivot, False Exit Else i = i + 1 EndIf Forever i = 0 Return |
| ||
Working example would be helpful :) I guess some vector calc goes wrong because camera moves/rotates.. I'll try to check how camera movement/rotation affects alignment on my simple example.. edit: Yep, if I move the camera then "tube to cam" vector calc goes nuts.. back to bug hunt :) |
| ||
Okay, here's my entire code. Apart from the player model itself, everything should be in working order. I changed the player model to a cone for you. Most non-essential code covering other things has been removed. graphicsX = 1280 graphicsY = 1024 Graphics3D graphicsX, graphicsY, 32, 1 SetBuffer = BackBuffer() AntiAlias True WBuffer True frameTimer = CreateTimer(60) Type userType Field currentMode$ End Type user.userType = New userType user\currentMode = "FreeCamera" Type weaponType Field xOffset#, yOffset#, zOffset#, weaponName$, charge#, requiredCharge#, ammunition, heat#, hitPoints#, model End Type Type fighterType Field model, speed#, inertiaRating#, primaryWeapon.weaponType End Type player.fighterType = New fighterType player\primaryWeapon.weaponType = New weaponType Type laserType Field pivot, sprite, colour$, status$, speed#, damage#, range#, distanceTravelled# Field x#, y#, z#, x2#, y2#, z2#, cx#, cy#, cz#, tx#, ty#, tz#, vx#, vy#, vz# End Type Dim laserArray.laserType(9999) For i = 0 To 9999 laserArray(i) = New laserType laserArray(i)\status = "Dead" Next BlueLaserSprite = LoadSprite("C:\Documents and Settings\James Robinson\Desktop\Stuff\Blitz and Idea\Blitz3D\MY PROGRAMS\Star Wars\Sprites and Textures\BlueLaser.bmp", 1+8+16+32) Gosub LoadAllModels ; Create required pivots masterPivot = CreatePivot() PositionEntity masterPivot, 0, 0, -120000 cameraPivot = CreatePivot(masterPivot) playerPivot = CreatePivot(masterPivot) ; Create Player player\model = createcone(8, True, playerPivot) ; The player model should point towards the star initially. PositionEntity player\model, EntityX(masterPivot), EntityY(masterPivot), EntityZ(masterPivot) EntityParent player\model, playerPivot ; Important! All game models are hidden initially. ShowEntity player\model ; Create a camera and make cameraPivot the parent of the camera. camera = CreateCamera(cameraPivot) TranslateEntity camera, 0, 0, -30 CameraRange camera, 1, 99999999999 ; Create a light. light = CreateLight() RotateEntity light, 90, 0, 0 ; Create a star and define a pivot to orbit the planets around. star = CreateSphere(32) PositionEntity star, 0, 0, 0 EntityColor star, 255, 150, 0 ScaleEntity star, 60000, 60000, 60000 ; Hide mouse pointer and move to screen center initially. HidePointer MoveMouse 640, 512 While Not KeyDown(1) WaitTimer(frameTimer) ; Make player's ship move Gosub playerMovement ; Fire Player's Primary Weapons If MouseHit(1) Gosub playerPrimaryWeapons EndIf ; Keep Track of all Weapons Gosub Weapons ; Change Ship Control Mechanism If MouseHit(2) If user\currentMode = "FreeCamera" user\currentMode = "MousePilot" ElseIf user\currentMode = "MousePilot" user\currentMode = "FreeCamera" EndIf EndIf ; Allows rotation of the camera around the player with the mouse. Gosub cameraRotate ; Allow turning of ship with mouse If user\currentMode = "MousePilot" Gosub MousePilot EndIf RenderWorld Flip True Wend End .playerMovement ; A to increase speed If KeyDown(30) player\speed = player\speed + 1 EndIf ; Z to decrease speed If KeyDown(44) player\speed = player\speed - 1 EndIf ; SHIFT-A to enter cruise mode If KeyDown(30) And KeyDown(42) player\speed = 500 EndIf ; SHIFT-Z for emergency stop If KeyDown(44) And KeyDown(42) player\speed = 0 EndIf TranslateEntity masterPivot, -player\speed*Sin(EntityYaw(playerPivot)), -player\speed*Sin(EntityPitch(playerPivot)), player\speed*Cos(EntityYaw(playerPivot)) Return .MousePilot If EntityYaw(cameraPivot) >= 0 And EntityYaw(playerPivot) >= 0 If EntityYaw(cameraPivot) > EntityYaw(playerPivot) + 1 TurnEntity playerPivot, 0, 1/player\inertiaRating, 0 ElseIf EntityYaw(cameraPivot) < EntityYaw(playerPivot) - 1 TurnEntity playerPivot, 0, -1/player\inertiaRating, 0 EndIf ElseIf EntityYaw(cameraPivot) < 0 And EntityYaw(playerPivot) < 0 If EntityYaw(cameraPivot) > EntityYaw(playerPivot) + 1 TurnEntity playerPivot, 0, 1/player\inertiaRating, 0 ElseIf EntityYaw(cameraPivot) < EntityYaw(playerPivot) - 1 TurnEntity playerPivot, 0, -1/player\inertiaRating, 0 EndIf ElseIf EntityYaw(cameraPivot) >= 0 And EntityYaw(playerPivot) < 0 If EntityYaw(cameraPivot) - EntityYaw(playerPivot) > 180 TurnEntity playerPivot, 0, -1/player\inertiaRating, 0 Else TurnEntity playerPivot, 0, 1/player\inertiaRating, 0 EndIf ElseIf EntityYaw(cameraPivot) < 0 And EntityYaw(playerPivot) >= 0 If EntityYaw(playerPivot) - EntityYaw(cameraPivot) > 180 TurnEntity playerPivot, 0, 1/player\inertiaRating, 0 Else TurnEntity playerPivot, 0, -1/player\inertiaRating, 0 EndIf EndIf If EntityPitch(playerPivot) > EntityPitch(cameraPivot) + 1 TurnEntity playerPivot, -1/player\inertiaRating, 0, 0 ElseIf EntityPitch(playerPivot) < EntityPitch(cameraPivot) - 1 TurnEntity playerPivot, 1/player\inertiaRating, 0, 0 EndIf Return .Weapons For i = 0 To 9999 If laserArray(i)\status = "Alive" TranslateEntity laserArray(i)\pivot, -laserArray(i)\speed*Sin(EntityYaw(laserArray(i)\pivot)), -laserArray(i)\speed*Sin(EntityPitch(laserArray(i)\pivot)), laserArray(i)\speed*Cos(EntityYaw(laserArray(i)\pivot)) laserArray(i)\x# = EntityX(laserArray(i)\pivot, True) laserArray(i)\y# = EntityY(laserArray(i)\pivot, True) laserArray(i)\z# = EntityZ(laserArray(i)\pivot, True) laserArray(i)\x2# = EntityX(camera, True) laserArray(i)\y2# = EntityY(camera, True) laserArray(i)\z2# = EntityZ(camera, True) laserArray(i)\cx# = laserArray(i)\x# - laserArray(i)\x2# laserArray(i)\cy# = laserArray(i)\y# - laserArray(i)\y2# laserArray(i)\cz# = laserArray(i)\z# - laserArray(i)\z2# TFormVector 0,0,0, laserArray(i)\pivot,0 laserArray(i)\tx# = TFormedX() laserArray(i)\ty# = TFormedY() laserArray(i)\tz# = TFormedZ() laserArray(i)\vx# = laserArray(i)\cy# * laserArray(i)\tz# - laserArray(i)\cz# * laserArray(i)\ty# laserArray(i)\vy# = laserArray(i)\cz# * laserArray(i)\tx# - laserArray(i)\cx# * laserArray(i)\tz# laserArray(i)\vz# = laserArray(i)\cx# * laserArray(i)\ty# - laserArray(i)\cy# * laserArray(i)\tx# AlignToVector(laserArray(i)\sprite, laserArray(i)\vx#, laserArray(i)\vy#, laserArray(i)\vz#, 1) AlignToVector(laserArray(i)\sprite, laserArray(i)\tx#, laserArray(i)\ty#, laserArray(i)\tz#, 2) EndIf Next Return .playerPrimaryWeapons i = 0 Repeat If laserArray(i)\status = "Dead" ; Speed and other variables should be set here, determined by what weapon is firing. laserArray(i)\status = "Alive" laserArray(i)\speed = 0.1 laserArray(i)\pivot = CreatePivot() PositionEntity laserArray(i)\pivot, EntityX(masterPivot), EntityY(masterPivot), EntityZ(masterPivot) RotateEntity laserArray(i)\pivot, EntityPitch(playerPivot), EntityYaw(playerPivot), 0 ;Set Up Laser Sprite laserArray(i)\sprite = CopyEntity(BlueLaserSprite) SpriteViewMode laserArray(i)\sprite, 4 ScaleSprite laserArray(i)\sprite, 1, 10 EntityFX laserArray(i)\sprite, 17 EntityParent laserArray(i)\sprite, laserArray(i)\pivot, False Exit Else i = i + 1 EndIf Forever i = 0 Return .cameraRotate ; zoom camera in If KeyDown(78) TranslateEntity camera, 0, 0, 0.1 EndIf ; zoom camera out If KeyDown(74) TranslateEntity camera, 0, 0, -0.1 EndIf ; Ensure that the mouse never leaves the screen bounds. If ( MouseX() > 1200 ) Or ( MouseX() < 50 ) Or ( MouseY() > 1000 ) Or ( MouseY() < 50 ) Then MoveMouse 640, 512 EndIf ; Turn cameraPivot, thus making camera spin around it. Note that the vertical speed is set ; to be less than the horizontal speed. TurnEntity cameraPivot, MouseYSpeed() / 1.5, -MouseXSpeed(), 0 ; Always keep cameraPivot's roll 0 wrt the horizontal plane. RotateEntity cameraPivot, EntityPitch(cameraPivot), EntityYaw(cameraPivot), 0 Return |
| ||
ok heres my code for creating beams.. - note that this version alters the verts per frame... Graphics3D(640,480,32,2) cam=CreateCamera() CameraRange(cam,1,1000) PositionEntity(cam,0,0,-5) ray.gfx_ray=gfx_createray(0.5,255,0,0,0.7) ;create our ray.. s=CreateSphere(8) PositionEntity(s,10,0,100) While Not KeyHit(1) Cls() PositionEntity(cam,EntityX(cam,True)+MouseXSpeed()*0.1,EntityY(cam,True)+MouseYSpeed()*0.1,0) MoveMouse(320,240) gfx_castray(ray,cam,10,0,100,-10,0,0) ;rayupdate UpdateWorld() RenderWorld() Flip() Wend End ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;RAYCAST GFX Type gfx_ray Field mesh Field surf Field rad# End Type ;GFX_CREATERAY() ;creates the basic ray object..this object can be textured, but defaults ;to a red fullbright ray.. Function gfx_createray.gfx_ray(rad#=1,r=255,g=0,b=0,a#=1.0) ray.gfx_ray=New gfx_ray ray\mesh=CreateMesh() ray\surf=CreateSurface(ray\mesh) AddVertex(ray\surf,0,0,0,0,1) ;0 BL = bottom left AddVertex(ray\surf,0,0,0,0,0) ;1 TL AddVertex(ray\surf,0,0,0,1,1) ;2 BR AddVertex(ray\surf,0,0,0,1,0) ;3 TR AddTriangle(ray\surf,0,1,2) AddTriangle(ray\surf,3,2,1) EntityColor(ray\mesh,r,g,b) EntityAlpha(ray\mesh,a) EntityFX(ray\mesh,1) ray\rad=rad Return ray End Function ;GFX_CASTRAY() ;Sets rays vertices.. ; - ray = previously created ray object. ; - viewer = should be a camera entity..or the object the camera ; is mounted to.. ; - x1,y1,z1 = startpoint of ray - typically some kind of emitter ; - x2,y2,z2 = end point of ray.. Function gfx_castray(ray.gfx_ray,viewer,x1#,y1#,z1#,x2#,y2#,z2#) vx#=EntityX(viewer,True) vy#=EntityY(viewer,True) vz#=EntityZ(viewer,True) vx=vx-x1 vy=vy-y1 vz=vz-z1 x3#=x2-x1 y3#=y2-y1 z3#=z2-z1 cx1#=vy*z3-vz*y3 cy1#=vz*x3-vx*z3 cz1#=vx*y3-vy*x3 clen#=Sqr(cx1*cx1+cy1*cy1+cz1*cz1) cx1=(cx1/clen)*ray\rad cy1=(cy1/clen)*ray\rad cz1=(cz1/clen)*ray\rad cx2#=-cx1 cy2#=-cy1 cz3#=-cz1 VertexCoords(ray\surf,0,x1+cx1,y1+cy1,z1+cz1) VertexCoords(ray\surf,1,x1+cx2,y1+cy2,z1+cz2) VertexCoords(ray\surf,2,x2+cx1,y2+cy1,z2+cz1) VertexCoords(ray\surf,3,x2+cx2,y2+cy2,z2+cz2) End Function |