Posted: 12th Jan 2016 21:09
I recently wrote some billboarding code for a project and it worked so well I decided to port it to DBPro.

+ Code Snippet
// Example: Optimized Arbitrary Axis Aligned Billboarding via Manual World Matrix Construction
// By: Jesse George (revenant_chaos@yahoo.com) Jan/2016
//////////////////////////////////////////////////////////////////////////////////////////////////
Set Display Mode 1024,768,32,1
Sync On : Sync Rate 0
color Backdrop RGB(14,19,25)
autocam off
move camera -100
 
//custom Vec3 structure
	Type Vector3
		X as float
		Y as float
		Z as float
	endtype
 
//Load Basic3D Dll (for SetWorldMatrix() function)
	Global dll_Basic3D as integer : dll_Basic3D = 1
	Load Dll "DBProBasic3DDebug.dll", dll_Basic3D
 
 
 
 
 
//Prepare Laser Object
	ObjID=1
	Make Object Plane ObjID,1,1,1
   Rotate Object ObjID,-90,-90,0
   `re-create the object from mesh to "fix" the object's rotation
	make Mesh From Object 1,ObjID : Delete Object ObjID
	Make Object ObjID,1 : Delete Mesh 1
	`disable the object's culling, dbpro can't properly cull objects which use custom world matrices
	Set Object Radius ObjID,0
	`disable the object's lighting; the object's normals will not be transformed properly due to
	`some shortcuts (optimizations) used in this example.
	set object light ObjID,0
	`load and apply texture
	TexID=1
	load image "LaserBeam.png",TexID
	texture object ObjID,TexID
	ghost object on ObjID,2
 
 
 
 
//Allocate and Initalize Matrix4x4 structure. Will be used as a world transformation matrix
	Global MatPtr as Dword
	`16floats = 64bytes
	MatPtr = MAKE MEMORY(64)
	`Prepare matrix element pointers
	m11=MatPtr    :    m12=MatPtr+4  :    m13=MatPtr+8  :    m14=MatPtr+12
	m21=MatPtr+16 :    m22=MatPtr+20 :    m23=MatPtr+24 :    m24=MatPtr+28
	m31=MatPtr+32 :    m32=MatPtr+36 :    m33=MatPtr+40 :    m34=MatPtr+44
	m41=MatPtr+48 :    m42=MatPtr+52 :    m43=MatPtr+56 :    m44=MatPtr+60
	`setup some values here to avoid doing so within the main loop
	*m14=0.0 : *m24=0.0 : *m34=0.0 : *m44=1.0
	*m21=0.0 : *m22=1.0 : *m23=0.0 `binormal doesnt matter for this application
    
 
//Initalize some vectors to use for matrix assembly
	`TBN vectors (Rotation and Scale)
	Tangent as Vector3
	Binormal as Vector3
	Normal as Vector3
	`Translation vector
	Translation as Vector3
 
 
     
//Initalize laser beam Vecs and Vars
	`Vectors Laser's Beginning and End points
	Origin as Vector3
	Destination as Vector3
	`Laser's Beam Width
	BeamWidth as float
	BeamWidth = 5.0
 
	`make some spheres for the laser's end points
	make object sphere 2,5
	make object sphere 3,5

Ink RGB(192,128,0)
do
	set cursor 0,0
 	Print "Use the Mouse and Arrowkeys to navigate"
 	Print "Use the Mousewheel to adjust billboard width"
 
//Camera navigation
	move camera (upkey()-downkey())*4
	move camera right (rightkey()-leftkey())*4 `Matrix1Utils
	rotate camera wrapvalue(camera angle X()+(mousemoveY()*0.2)),wrapvalue(camera angle Y()+(mousemoveX()*0.2)),0

	`Adjust beam width using mousewheel
	MMZ = MouseMoveZ()
	if MMZ
		if MMZ>0
			Inc BeamWidth
		else
			Dec BeamWidth
		endif
	endif


//Update Laser
	`temp angle for laser movement
	TmpAng# = wrapvalue(timer()*0.05)
 
	`set the laser's origin
	Origin.X = -Sin(TmpAng#)*80
	Origin.Y = -100
	Origin.Z = -Cos(TmpAng#)*80
	position object 2,Origin.X,Origin.Y,Origin.Z
 
	`set the laser's destination
	Destination.X = Sin(TmpAng#)*100
	Destination.Y = 100
	Destination.Z = Cos(TmpAng#)*100
	position object 3,Destination.X,Destination.Y,Destination.Z

	`calculate the laser's center
	Translation.X = ( Origin.X + Destination.X ) * 0.5
	Translation.Y = ( Origin.Y + Destination.Y ) * 0.5
	Translation.Z = ( Origin.Z + Destination.Z ) * 0.5
 
	`calculate the laser's direction vector (non-normalized to preserve scaling)
	Tangent.X = Destination.X - Origin.X
	Tangent.Y = Destination.Y - Origin.Y
	Tangent.Z = Destination.Z - Origin.Z
 
	`get a vector from the laser to the camera (non-normalized, doesnt matter....)
	Binormal.X = Translation.X - Camera Position X()
	Binormal.Y = Translation.Y - Camera Position Y()
	Binormal.Z = Translation.Z - Camera Position Z()
 
	`Normal = Tangent <cross> Binormal
	Normal.X = (Tangent.Y*Binormal.Z) - (Tangent.Z*Binormal.Y)
	Normal.Y = (Tangent.Z*Binormal.X) - (Tangent.X*Binormal.Z)
	Normal.Z = (Tangent.X*Binormal.Y) - (Tangent.Y*Binormal.X)
 
	`scale normal vector's length to match the desired beam width
	tmp# = (((Normal.X*Normal.X)+(Normal.Y*Normal.Y)+(Normal.Z*Normal.Z))^0.5)/BeamWidth
	Normal.X = Normal.X / tmp#
	Normal.Y = Normal.Y / tmp# 
	Normal.Z = Normal.Z / tmp#
 
	`assemble world matrix
	*m11=Tangent.X
	*m12=Tangent.Y
	*m13=Tangent.Z
	*m31=Normal.X
	*m32=Normal.Y
	*m33=Normal.Z
	*m41=Translation.X
	*m42=Translation.Y
	*m43=Translation.Z
    
	`apply the world transformation matrix to the laser object
	call dll dll_Basic3D,"?SetWorldMatrix@@YAXHPAUD3DXMATRIX@@@Z",ObjID,MatPtr

	Sync
loop
 
 
 
Delete Memory MatPtr
Delete Dll dll_Basic3D



[Edit] Attached Laser Beam Image.
[Edit2] Fixed bug with matrix memory allocation; it appears MAKE MEMORY() does not ensure the memory is initialized with zeros...
Posted: 20th Jan 2016 7:48
Didn't DBP have a point object command that would do all this?
Posted: 21st Jan 2016 6:42
Not quite, Point object() uses XY rotation to point an object's local z-axis towards some point in space. The result of that operation does not define a Z-rotation angle because all values would be equally correct. Unfortunately, this means Point Object() is useless for anything other than point-sprite effects or global-axis oriented billboards (X or Y).

My example shows how to construct a world transformation matrix which aligns an object to an arbitrary axis (as defined by the laser's end-points), then rotates the object about that axis in an attempt to face towards a second point (the camera). The matrix also applies the proper scaling needed to achieve the desired beam width and length. I suppose it could be thought of as being Point Object() on steroids which attempts to align two of an object's local axis with two separate points in space.

In this example I've applied the world matrix directly to an object, but the matrix is also suitable for transforming vertexdata.
Posted: 23rd Jan 2016 6:36
Updated example to fix Make Memory() error, seems matrix memory was not initialized with zeros sometimes leading to improper transformations.
Posted: 11th Feb 2016 6:03
very cool man, this will be handy