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 |