Stupid OpenGL question

Stupid OpenGL question

Discuss Lua based Spring scripts (LuaUI widgets, mission scripts, gaia scripts, mod-rules scripts, scripted keybindings, etc...)

Moderators: Moderators, Moderators

User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Stupid OpenGL question

Post by Argh »

Um... if I have vertexes at positions XYZ (1,1,1), (-1,1,1), (1,1,-1), (-1,1,-1) and I want to draw a line strip between them, how do I do that? The few examples I've seen are using functions, but I don't want to call a function, I just want to give it vertex locations. How do I feed it some raw numbers? Sorry in advance, if this seems stupid or whatever, but the LUA OpenGL stuff doesn't look at all like the OpenGL reference materials I could find.

To put this into perspective, the reference I found for drawing lines with C++ was written like this:

glBegin(GL_LINE_STRIP);
glVertex3f(-1.0f, 1.0f, 0.0f);
glVertex3f(-0.5f, 0.5f, 0.0f);
glVertex3f(-0.7f, 0.5f, 0.0f);
glEnd();

However, the LUA OpenGL API requires that it be written like this:

gl.BeginEnd( number GLType, function [, arg1,... ] ) -> nil

... which I'm finding totally confusing. Why does it require a function?

What I want, basically, is to do some lines from positions XYZ --> XYZ, then do another set of lines, but with a different alpha value, and so on.
0 x

user
Posts: 452
Joined: 22 Jan 2008, 16:33

Re: Stupid OpenGL question

Post by user »

it should be like this:

gl.BeginEnd(GL.LINE_STRIP,function()
gl.Vertex(-1.0, 1.0, 0.0)
gl.Vertex(-0.5, 0.5, 0.0)
gl.Vertex(-0.7, 0.5, 0.0)
End)
0 x

user
Posts: 452
Joined: 22 Jan 2008, 16:33

Re: Stupid OpenGL question

Post by user »

i recommend using a display list, it is much faster.

to use a list, make a "global" variable, then do this at initialize:

<variable name> = gl.CreateList(function()
<drawing functions here>
end)

then to call it use gl.Translate, to move it to where you want, then use
gl.CallList(<list name>)
0 x

User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Stupid OpenGL question

Post by Argh »

Hmm.

Ok, first off, here's what I've got, minus the information supply and COB-side stuff (that stuff works):

Code: Select all

SYNC, CALLED FROM COB
--////////////////////////////////////////////////////////////////////
function DrawLinePrimitive(PosX,PosY,PosZ,OldPosX,OldPosY,OldPosZ)

	SendToUnsynced("onFire",PosX,PosY,PosZ,OldPosX,OldPosY,OldPosZ)
		
end
gadgetHandler:RegisterGlobal("DrawLinePrimitive", DrawLinePrimitive)
--////////////////////////////////////////////////////////////////////
So, COB calls that, and supplies the arguments for all of the positions. That stuff is working.

Next, because I apparently cannot just draw without going to unsync, I send it over:

Code: Select all

--////////////////////////////////////////////////////////////////////
function RecvFromSynced(...)
  	if (arg[2] == 'onFire') then DrawWorld(arg[8])

	end
end
--////////////////////////////////////////////////////////////////////

--////////////////////////////////////////////////////////////////////
function gadget:DrawWorld()
	if (aircraftAlive) then
  	gl.Color(0,0.3,1,0.5)
	gl.LineWidth(1.0)

	gl.BeginEnd(GL.LINE_STRIP,function()
	gl.Vertex(PosX, PosY, PosZ)
	gl.Vertex(OldPosX, OldPosY, OldPosZ)
	gl.Vertex(-0.7, 0.5, 0.0)
	end)
	end
end	
--////////////////////////////////////////////////////////////////////
And then it fails, saying that I'm not supplying nil values for gl.Vertex. So... what's missing?
0 x

User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Stupid OpenGL question

Post by Argh »

Ok, what's missing is that the values for the gl.Vertex aren't working. Put those in, everything draws, yay.
0 x

user
Posts: 452
Joined: 22 Jan 2008, 16:33

Re: Stupid OpenGL question

Post by user »

not sure what is the problem, probably the variables dont get sent when it is called.

try using this:

Code: Select all


local posx,posy,posz,oldposx,oldposy,oldposz = 0
local draw = 0

--////////////////////////////////////////////////////////////////////
function RecvFromSynced(...)
     if (arg[2] == 'onFire') then 
          <set the values to the globals>    
          draw = 1
     end
end
--////////////////////////////////////////////////////////////////////

--////////////////////////////////////////////////////////////////////
function gadget:DrawWorld()
   if (aircraftAlive) then
      if (draw==1)
         gl.Color(0,0.3,1,0.5)
        gl.LineWidth(1.0)
  
        gl.BeginEnd(GL.LINE_STRIP,function()
            gl.Vertex(PosX, PosY, PosZ)
            gl.Vertex(OldPosX, OldPosY, OldPosZ)
            gl.Vertex(-0.7, 0.5, 0.0)
        end)
        draw = 0 
        <set the variables values to 0> 
      end
   end
end   
--////////////////////////////////////////////////////////////////////
this is the best way i can think of making this.

Code: Select all

gl.Vertex(-0.7, 0.5, 0.0)
this will make it get get drawn at the border of the map, you should change it.
0 x

User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Stupid OpenGL question

Post by Argh »

Basically, what I'm trying to write here is a nice, simple ribbon-trail FX for everybody who wants to make trails for stuff. I figured it was something people wanted, and meh, it was about time for me to start digging into OpenGL for Spring.

This started out with a lot of very messy COB --> LUA. That turned out to be a fairly bad idea, since almost all of the data I actually need is over on the LUA side anyhow (with the rather important exception of not being able to get a worldspace coordinate for a particular Piece, but meh, I can probably get around that, by calculating some offsets, once the basic code works).


I'm a little closer to a solution, but once again, the issue of tables is stumping me.

Code: Select all

PosTable = {}

AirCraft = {
    [UnitDefNames.scoutcraft.id] = "scoutcraft",
}
--////////////////////////////////////////////////////////////////////
function gadget:GameFrame(f)
	for _,u in ipairs(Spring.GetAllUnits()) do
		if AirCraft[Spring.GetUnitDefID(u)] then
			Spring.Echo(PostTable[1])
			PosTable.OldPosX = PosTable.PosX
			PosTable.OldPosY = PosTable.PosY
			PosTable.OldPosZ = PosTable.PosZ		
			local x,y,z = Spring.GetUnitPosition(u)
			PosTable.PosX = x
			PosTable.PosY = y
			PosTable.PosZ = z
		end
	end
end	
--////////////////////////////////////////////////////////////////////

--/////////////////////////////////////////////////////////////////////////////////////////////////////////////
--////////////////////////////////////////////////////////////////////////////////////////END OF SYNC FUNCTIONS
--/////////////////////////////////////////////////////////////////////////////////////////////////////////////
else
--////////////////////////////////////////////////////////////////////
function gadget:DrawWorld(u)
	for _,u in ipairs(Spring.GetAllUnits()) do
		if AirCraft[Spring.GetUnitDefID(u)] then
		  	gl.Color(0,0.3,1,0.5)
			gl.LineWidth(1.0)
		    Spring.Echo(PosTable[1])
			gl.BeginEnd(GL.LINE,function()
			--gl.Vertex(u.PosX,u.PosY,u.PosZ)
			--gl.Vertex(u.OldPosX,u.OldPosY,u.OldPosZ)
			end)
		end
	end
end	
--////////////////////////////////////////////////////////////////////
After much fighting with the code, I belatedly realized that the only way to make this work is if I store a list of all points, new and old, to use as the source of my vertexes. That part's not working, and I can't seem to get it to work, either. What I need is a table, "PosTable", which stores, in pairs, unitIDs and a sub-table of PosX, PosY, PosZ, etc., etc.

I can't seem to figure out how to make this part, which is probably the easiest bit. If I had that, I could get back to working on the trig side, and see if I can do anything nicer than from the Unit's centroid...
0 x

user
Posts: 452
Joined: 22 Jan 2008, 16:33

Re: Stupid OpenGL question

Post by user »

make it a 2d array, that should be like this:

<name>[<number>][10]

then make a function to check for units created, and then add them to
<table name>[<unitid>][0].

then on a update function:

Code: Select all

function gadget:update()
     if (Spring.GetGameFrame() % 90 == 0) then
         <then do a loop for every table variable>
         <set the current values to the old values table,>
         <set the new values to the new value table>                
     end
end


then on draw, just use the values.
0 x

User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Stupid OpenGL question

Post by Argh »

Ok, so I (almost) have everything working. I finally sorted out how to build a table and stuff. Now I just need to figure out how to get the packed coordinates from COB over to LUA.

The only trouble remaining is that this doesn't seem to work:

Spring.GetCOBUnitVar

( number unitID, integer varID [, boolean unpack = false ] )
-> nil | number value | number unpackedX, number unpackedY

Now, maybe I'm just mis-reading this, but if I set up my COB like this:

Code: Select all

static-var X;

SomeScript()
{
  X = 1;
}
And I have a line like this, in LUA;

Code: Select all

local x = Spring.GetCOBUnitVar(u,1)
Where u == UnitID of the Unit, it returns a value of nil. What's up with that? The only other way I can do this is by manually unpacking the coordinates, and I don't know how to do that, either :P
0 x

User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Stupid OpenGL question

Post by Argh »

Everything works, except for one thing: I can't seem to get the Unsync side to see the values stored in my table. Any ideas? It's the only part of this that isn't working now...

Code: Select all

function gadget:GetInfo()
	return {
		name = "Trails.lua",
		desc = "Draws trails behind fighters.",
		author = "Argh",
		date = "February 21st, 2007",
		license = "Public Domain",
		layer = 1,
		enabled = true,
	}
end

local TrailQueue = {}

if (gadgetHandler:IsSyncedCode()) then
--////////////////////////////////////////////////////////////////BEGIN SYNC

--////////////////////////////////////////////////////////////////////////////
function GetValues(u,ud,team)
	local x,y,z = Spring.GetUnitPosition(u)
	return x,y,z
end
gadgetHandler:RegisterGlobal("GetValues", GetValues)
--////////////////////////////////////////////////////////////////////////////

--////////////////////////////////////////////////////////////////////////////
function SendOverValues(u,ud,team,X1,Y1,Z1,X2,Y2,Z2)
	table.insert(TrailQueue,{x1=X1,y1=Y1,z1=Z1,x2=X2,y2=Y2,z2=Z2})
	--[[for _,u in ipairs(TrailQueue) do
	Spring.Echo (u.x1,u.y1,u.z1) end]]
end
gadgetHandler:RegisterGlobal("SendOverValues", SendOverValues)
--////////////////////////////////////////////////////////////////////////////

--////////////////////////////////////////////////////////////////END SYNC
else
--////////////////////////////////////////////////////////////////BEGIN UNSYNC

--////////////////////////////////////////////////////////////////////////////
function gadget:DrawWorld()
	for _,u in ipairs(TrailQueue) do
	Spring.Echo (u.x1,u.y1,u.z1) end			
			gl.Color(0,0.3,1,0.5)
			gl.LineWidth(1.0)
	for _,t in ipairs(TrailQueue) do
			gl.BeginEnd(GL.LINE_STRIP,function()
			gl.Vertex(t.x1,t.y1,t.z1)
			gl.Vertex(t.x2,t.y2,t.z2)
			end)
	end	 
end
--////////////////////////////////////////////////////////////////////////////

--////////////////////////////////////////////////////////////////END UNSYNC
end
That call in DrawWorld() to iterate the values stored in TrailQueue does nothing- not even an error message. However, putting in a Spring.Echo to print the value "test" works just fine. Obviously that code is running. So, wtf is wrong, here? All I need is for DrawWorld() to see TrailQueue's values, and I'm in business...
0 x

user
Posts: 452
Joined: 22 Jan 2008, 16:33

Re: Stupid OpenGL question

Post by user »

try using unpack(<name of array>).
0 x

User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Stupid OpenGL question

Post by Argh »

Ok, so... how do I make a display list? I've tested it with 300 fighters, and it's going to drag people's machines to a halt if I don't figure out a way to speed it up.

For those not following the haphazard progress of this attempt, in multiple threads...

COB:

Code: Select all

lua_GetValues(arg){return 0;}
lua_SendOverValues(arg){return 0;}

positionUpdate()
{
	while(1)
	{
		call-script lua_GetValues();
		X1 = GET LUA1;
		Y1 = GET LUA2;
		Z1 = GET LUA3;
		call-script lua_SendOverValues(X1,Y1,Z1,X2,Y2,Z2);
		sleep 1000;
		X2 = X1;
		Y2 = Y1;
		Z2 = Z1;	
	}
}
LUA:

Code: Select all

function gadget:GetInfo()
	return {
		name = "Trails.lua",
		desc = "Draws trails behind fighters.",
		author = "Argh",
		date = "February 21st, 2007",
		license = "Public Domain",
		layer = 1,
		enabled = true,
	}
end

if (gadgetHandler:IsSyncedCode()) then

local TrailQueue = {}
--////////////////////////////////////////////////////////////////BEGIN SYNC

--////////////////////////////////////////////////////////////////////////////
function GetValues(u,ud,team)
	local x,y,z = Spring.GetUnitPosition(u)
	return x,y,z
end
gadgetHandler:RegisterGlobal("GetValues", GetValues)
--////////////////////////////////////////////////////////////////////////////

--////////////////////////////////////////////////////////////////////////////
function SendOverValues(u,ud,team,X1,Y1,Z1,X2,Y2,Z2)
	table.insert(TrailQueue,{x1=X1,y1=Y1,z1=Z1,x2=X2,y2=Y2,z2=Z2})
end
gadgetHandler:RegisterGlobal("SendOverValues", SendOverValues)
--//////////////////////////////////////////////////////////////////////////// 

function gadget:Initialize()
gadgetHandler:RegisterGlobal("TrailQueue", TrailQueue)
end
--////////////////////////////////////////////////////////////////END SYNC
else
--////////////////////////////////////////////////////////////////BEGIN UNSYNC

--////////////////////////////////////////////////////////////////////////////
function gadget:DrawWorld()
			gl.Color(0,0.3,1,0.5)
			gl.LineWidth(1.0)
	for _,t in spairs(SYNCED.TrailQueue) do
			gl.BeginEnd(GL.LINE_STRIP,function()
			gl.Vertex(t.x1,t.y1,t.z1)
			gl.Vertex(t.x2,t.y2,t.z2)
			end)
	end		 
end
--////////////////////////////////////////////////////////////////////////////

--////////////////////////////////////////////////////////////////END UNSYNC
end
0 x

user
Posts: 452
Joined: 22 Jan 2008, 16:33

Re: Stupid OpenGL question

Post by user »

you need to activate the depth buffer here, or the trails will be draw in the front of anything.

Code: Select all

function gadget:DrawWorld()
   gl.Color(0,0.3,1,0.5)
   gl.LineWidth(1.0)
   gl.DepthTest(true) 
   for _,t in spairs(SYNCED.TrailQueue) do
         gl.BeginEnd(GL.LINE_STRIP,function()
         gl.Vertex(t.x1,t.y1,t.z1)
         gl.Vertex(t.x2,t.y2,t.z2)
         end)
   end      
   gl.DepthTest(false) 
end
to set up the list:

Code: Select all


local Trail

local DrawTrail = function(<whatever>) 
      gl.BeginEnd(GL.LINE_STRIP, function()
         gl.Vertex(t.x1,t.y1,t.z1)
         gl.Vertex(t.x2,t.y2,t.z2)
         <or whatever you want>
      end 
end      

function gadget:Initialize()
     gadgetHandler:RegisterGlobal("TrailQueue", TrailQueue)
     Trail = gl.CreateList(DrawTrail,<some default values>)   
end
to call it, the hard part:

Code: Select all

function gadget:DrawWorld()
   gl.Color(0,0.3,1,0.5)
   gl.LineWidth(1.0)
   gl.DepthTest(true) 
   for _,t in spairs(SYNCED.TrailQueue) do
         gl.PushMatrix()
         gl.Translate(<unit position>)
         gl.Rotate(<the angle between the 2 points>) 
         gl.Scale(<whatever>)
         gl.CallList(Trail)
         gl.PopMatrix()
         <maybe use gl.ResetMatrices()>
   end      
   gl.DepthTest(false) 
end
the default values for the list should be:

Code: Select all

function gadget:Initialize()
     gadgetHandler:RegisterGlobal("TrailQueue", TrailQueue)
     Trail = gl.CreateList(DrawTrail,0,0,0,0,0,16)   
end
that will create a line from 0,0,0 map coordinate to 0,0,16.

to correctly draw it you need to translate and rotate it to the place, scale if you really need.

making this seems to be hard, and it is, it is harder than using begin end, but much faster, i allways use lists, even when using begin end is way easier.

here you should make some new values to the table:
(creation time, trail life time, line width, rgba color, <and whatever you want>)

Code: Select all

function SendOverValues(u,ud,team,X1,Y1,Z1,X2,Y2,Z2)
 table.insert(TrailQueue,{x1=X1,y1=Y1,z1=Z1,x2=X2,y2=Y2,z2=Z2,f=Spring.GetGameFrame(),m=<make a max trail life variable,l = <the line width>,r = <color>,g = <color>,b = <color>,a = <color>}) 
end
and a very slow update function:

Code: Select all

function gadget:Update()
     if (Spring.GetGameFrame() % 150 == 0) then <every 5 seconds>
            for _,i in spairs(SYNCED.TrailQueue) do                 
                   if (i.f < Spring.GetGameFrame() -  i.m) then  
                         table.remove(i)                   
                   end
            end                           
    end 
end
you should also make a custom unit def value that has color, line width data, and max trail life, so that it is more customizable.

the gl.LineWidth, and gl.Color functions should be called for every TrailQueue, and look at its custom values.

to make the values work, they should be read when setting up TrailQueue values.

Code: Select all

function SendOverValues(u,ud,team,X1,Y1,Z1,X2,Y2,Z2)
you have there unitID,unitDefID and teamID on the function, use the unitDefID to read from the unit file.

i hope that this works, and that it helps.
0 x

User avatar
jK
Spring Developer
Posts: 2299
Joined: 28 Jun 2007, 07:30

Re: Stupid OpenGL question

Post by jK »

@argh:
1. Why do you send the UnitPos from Lua to Cob and then back to Lua??? That doesn't make sense at all!

2.
Argh wrote:Spring.GetCOBUnitVar
( number unitID, integer varID [, boolean unpack = false ] )
-> nil | number value | number unpackedX, number unpackedY
first, you picked the wrong function, you want GetUnitCOBValue() which is the cob-get function (Spring.GetCOBUnitVar() accesses trepan's new custom get-vars, but not local defined variables).

3.So you don't need any COB-changes at all, you want:

Code: Select all

  local PIECE_XZ = 7
  local PIECE_Y = 8
  local x,z   = Spring.GetUnitCOBValue(unitID,true,PIECE_XZ,piece)
  local y     = Spring.GetUnitCOBValue(unitID,PIECE_Y,piece)/COBSCALE
4.
Argh wrote: for _,t in spairs(SYNCED.TrailQueue) do
gl.BeginEnd(GL.LINE_STRIP,function()
gl.Vertex(t.x1,t.y1,t.z1)
gl.Vertex(t.x2,t.y2,t.z2)
end)
end
why do you use GL_LINE_STRIP if you render only 1 line? it should be (for using GL_LINE_STRIP you would have to change your array format):

Code: Select all

  gl.BeginEnd(GL.LINES,function()
    for _,t in spairs(SYNCED.TrailQueue) do
       gl.Vertex(t.x1,t.y1,t.z1)
       gl.Vertex(t.x2,t.y2,t.z2)
    end
  end)

@user:
user wrote:

Code: Select all

function gadget:DrawWorld()
   gl.Color(0,0.3,1,0.5)
   gl.LineWidth(1.0)
   gl.DepthTest(true) 
   for _,t in spairs(SYNCED.TrailQueue) do
         gl.PushMatrix()
         gl.Translate(<unit position>)
         gl.Rotate(<the angle between the 2 points>) 
         gl.Scale(<whatever>)
         gl.CallList(Trail)
         gl.PopMatrix()
         <maybe use gl.ResetMatrices()>
   end      
   gl.DepthTest(false) 
end
you don't really think that this is the right way to do so???
using a displaylist to render 2 stupid vertices and putting a math-monster around it???
push-/pop-matrix,translate,rotate,scale are time intensive functions! also they don't make it any easier to handle those vertex positions, 'cus you would have to calc those angles and scales first in slow lua code!
(and no gl.ResetMatrices() isn't the right one either ...)
0 x

User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Stupid OpenGL question

Post by Argh »

Whew! That's a lot to digest, you two ;)

The COB-->LUA stuff was because I was using the wrong function, lemme see if that works like you said, if so, then I can just wipe out everything in the table, every few frames, and re-populate it with new data, delivered via COB. That'd save me a lot of trouble, especially if I can get exact Piece locations intact.

What is the value of COBSCALE?

The line-strip thing was because I was originally thinking that a line-strip was the way to go, however I'm not sure that's going to be a very good solution, for the final concept- people generally expect trails to visually get smaller and fade in alpha values, as a visual convention... so I was thinking I'd use a larger line for the first segment, with a "core" of alpha-value 1.0 using another line, then shrink it a bit, so forth and so on...
0 x

User avatar
Peet
Malcontent
Posts: 4381
Joined: 27 Feb 2006, 22:04

Re: Stupid OpenGL question

Post by Peet »

Argh wrote:What is the value of COBSCALE?
65536
0 x

User avatar
jK
Spring Developer
Posts: 2299
Joined: 28 Jun 2007, 07:30

Re: Stupid OpenGL question

Post by jK »

COBSCALE is a global var in LuaRules/LuaCob you don't need to define it
0 x

User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Stupid OpenGL question

Post by Argh »

Ah, so it's the linear constant... gotcha. Same applies for radian conversions?
0 x

User avatar
Peet
Malcontent
Posts: 4381
Joined: 27 Feb 2006, 22:04

Re: Stupid OpenGL question

Post by Peet »

Argh wrote:Ah, so it's the linear constant... gotcha. Same applies for radian conversions?
65536 COB rotation units = 360 degrees
<> = 182.0444
0 x

User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Stupid OpenGL question

Post by Argh »

Cool. Not that I have a use for that, at the moment, but it'd be nice to know, when I do.
0 x

Post Reply

Return to “Lua Scripts”

cron