DxDrawPrimitive: Difference between revisions
Jump to navigation
Jump to search
mNo edit summary |
mNo edit summary |
||
(11 intermediate revisions by 6 users not shown) | |||
Line 1: | Line 1: | ||
__NOTOC__ | __NOTOC__ | ||
{{Client function}} | {{Client function}} | ||
This function draws a 2D primitive shape across the screen - rendered for one frame. This should be used in conjunction with [[onClientRender]] in order to display continuously. | {{New feature/item|3.0157|1.5.6|14370|This function draws a 2D primitive shape across the screen - rendered for one frame. This should be used in conjunction with [[onClientRender]] in order to display continuously.}} | ||
==Syntax== | ==Syntax== | ||
<syntaxhighlight lang="lua"> | <syntaxhighlight lang="lua"> | ||
bool dxDrawPrimitive ( | bool dxDrawPrimitive ( string pType, bool postGUI, table vertex1 [, table vertex2, ...] ) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Line 11: | Line 11: | ||
* '''pType:''' Type of primitive to be drawn. | * '''pType:''' Type of primitive to be drawn. | ||
* '''postGUI:''' A bool representing whether the line should be drawn on top of or behind any ingame GUI (rendered by CEGUI). | * '''postGUI:''' A bool representing whether the line should be drawn on top of or behind any ingame GUI (rendered by CEGUI). | ||
* '''vertices:''' Tables representing each primitive | * '''vertices:''' Tables representing each primitive vertex, required amount of them is determined by primitive type. | ||
==Allowed types== | ==Allowed types== | ||
Line 24: | Line 24: | ||
==Vertices format== | ==Vertices format== | ||
* '''posX:''' An float representing the absolute X position of the | * '''posX:''' An float representing the absolute X position of the vertex, represented by pixels on the screen. | ||
* '''posY:''' An float representing the absolute Y position of the | * '''posY:''' An float representing the absolute Y position of the vertex, represented by pixels on the screen. | ||
* '''color (optional):''' An integer of the hex color, produced using [[tocolor]] or 0xAARRGGBB (AA = alpha, RR = red, GG = green, BB = blue). If it's not specified, white color is used. | * '''color (optional):''' An integer of the hex color, produced using [[tocolor]] or 0xAARRGGBB (AA = alpha, RR = red, GG = green, BB = blue). If it's not specified, white color is used. | ||
Line 31: | Line 31: | ||
Returns a ''true'' if the operation was successful, ''false'' otherwise. | Returns a ''true'' if the operation was successful, ''false'' otherwise. | ||
==Example== | ==Example== | ||
This is a small example that creates trianglefan primitive with vertices in places that user clicks. It assigns every | <section name="Example 1" class="client" show="true"> | ||
This is a small example that creates trianglefan primitive with vertices in places that user clicks. It assigns every vertex random color. | |||
<syntaxhighlight lang="lua"> | <syntaxhighlight lang="lua"> | ||
local vertices = {} | local vertices = {} | ||
Line 38: | Line 39: | ||
if btn ~= "left" then return end | if btn ~= "left" then return end | ||
if state ~= "up" then return end | if state ~= "up" then return end | ||
local | local vertex = {x, y, tocolor(math.random(255), math.random(255), math.random(255))} | ||
table.insert(vertices, | table.insert(vertices, vertex) | ||
end | end | ||
addEventHandler("onClientClick", root, onClick) | addEventHandler("onClientClick", root, onClick) | ||
Line 48: | Line 49: | ||
addEventHandler("onClientPreRender", root, draw) | addEventHandler("onClientPreRender", root, draw) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
</section> | |||
<section name="Example 2" class="client" show="true"> | |||
This example draws one complete oscillation of a sine wave starting in the center of the players screen using a linestrip type primitive. | |||
<syntaxhighlight lang="lua"> | |||
local screenSizeX,screenSizeY = guiGetScreenSize() -- save the current screen dimensions | |||
local sinCoords = {} | |||
function resStart() -- do all this once during "onClientResourceStart", rather than every frame | |||
local range = math.pi * 2 -- to get 1 complete oscillation of the sine wave we need the range from 0 to 2pi | |||
local resolution = 100 -- resolution in this example means in how many steps we draw the linestrip, higher resolution means smoother curve at the expense of longer computation time and higher memory usage | |||
local scale = 50 | |||
for i=0,range,range/resolution do -- "loop through this [resolution] times, starting at 0 and ending at [range]" | |||
local x = screenSizeX * 0.5 + i * scale -- start at the center of the screen and go from there | |||
local y = screenSizeY * 0.5 - math.sin(i) * scale -- subtract rather than add because greater y value means lower on the screen, which is the opposite of what we're used to seeing in graphs | |||
table.insert(sinCoords,{x,y}) | |||
end | |||
end | |||
addEventHandler("onClientResourceStart",getResourceRootElement(getThisResource()), resStart) | |||
function exampleRender() | |||
dxDrawPrimitive("linestrip",true,unpack(sinCoords)) -- render a linestrip type primitive with the coordinates we calculated earlier to draw our sine wave | |||
end | |||
addEventHandler("onClientRender",getRootElement(),exampleRender) | |||
</syntaxhighlight> | |||
</section> | |||
<section name="Example 3" class="client" show="false"> | |||
Modifying the previous example, we can also use it to draw a "loading circle"-symbol similar to what some modern games like using to indicate loading or cloud saving in progress. | |||
<syntaxhighlight lang="lua"> | |||
local screenSizeX,screenSizeY = guiGetScreenSize() -- save the current screen dimensions | |||
local circleCoords = {} | |||
local resolution = 100 -- resolution in this example means in how many steps we draw the linestrip, higher resolution means smoother curve at the expense of longer computation time and higher memory usage | |||
local scale = 20 | |||
local maxSegmentPercentage = 0.75 -- this means the largest our line will get is 3/4 of the full circle | |||
local startPointRevolution = 2000 -- one full revolution around the circle for our starting point after this amount of milliseconds passed | |||
local endPointOscillation = 3000 -- one full oscillation of our endpoint after this amount of milliseconds passed | |||
function resStart() -- do all this once during "onClientResourceStart", rather than every frame | |||
local range = math.pi * 2 -- to complete a circle we need the range from 0 to 2pi | |||
for i=0,range,range/resolution do -- "loop through this [resolution] times, starting at 0 and ending at [range]" | |||
local x = screenSizeX * 0.5 + math.sin(i) * scale -- for a circle we get our x coordiante from sine and the y coordinate from cosine or vice versa | |||
local y = screenSizeY * 0.5 - math.cos(i) * scale -- subtract will later result in a clockwise spin, add in a counter clockwise one | |||
table.insert(circleCoords,{x,y}) | |||
end | |||
end | |||
addEventHandler("onClientResourceStart",getResourceRootElement(getThisResource()), resStart) | |||
function exampleRender() | |||
local tick = getTickCount() -- get the current time in milliseconds, then use it in a few clever ways to animate our circle | |||
local firstPoint = math.ceil( ((tick/startPointRevolution) % 1)*resolution ) -- firstly dividing it and using %1 (modulo 1) to repeatedly get a slowly, linearly increasing value from 0 to 1. This is our starting point | |||
local secondPoint = math.ceil( firstPoint + (math.sin(tick/endPointOscillation)) * resolution*maxSegmentPercentage ) -- secondly figuring out where we want our end point to be, using sine to get a pleasant looking pulse for the line growth | |||
if firstPoint > secondPoint then -- because of how we calculate our end point, half the time it will be smaller than the start point. for unpack() to give us the range we want we need to provide the smaller value first | |||
firstPoint, secondPoint = secondPoint, firstPoint | |||
end | |||
if secondPoint > resolution then -- sometimes we'll wrap around the origin point of our circle, those cases need to be taken care of, so we'll draw the linestrip in two parts for those. | |||
dxDrawPrimitive("linestrip",true,unpack(circleCoords,firstPoint,resolution)) -- [secondPoint] is overshooting, so first let's complete the circle from [firstPoint] | |||
dxDrawPrimitive("linestrip",true,circleCoords[resolution],unpack(circleCoords,1,secondPoint%resolution)) -- and then draw the remaining extra segments from the start of the circle to however many segments [secondPoint] went past [resolution] | |||
elseif firstPoint < 1 then -- lua tables start at an index of 1, so 0 and anything into the negatives needs to be handled | |||
dxDrawPrimitive("linestrip",true,unpack(circleCoords,resolution+firstPoint,resolution)) -- "how many segments before [resolution] do we have to start? Either way we complete it at [resolution]!" | |||
dxDrawPrimitive("linestrip",true,circleCoords[resolution],unpack(circleCoords,1,secondPoint)) -- draw the remaining segments from 1 all the way to [secondPoint] | |||
else | |||
dxDrawPrimitive("linestrip",true,unpack(circleCoords,firstPoint,secondPoint)) -- the line isn't currently crossing the origin point of the circle at the top, so drawing this one is straight forwards | |||
end | |||
end | |||
addEventHandler("onClientRender",getRootElement(),exampleRender) | |||
</syntaxhighlight> | |||
</section> | |||
==See Also== | ==See Also== | ||
{{Drawing_functions}} | {{Drawing_functions}} | ||
[[hu:dxDrawPrimitive]] |
Latest revision as of 06:32, 17 June 2023
This function draws a 2D primitive shape across the screen - rendered for one frame. This should be used in conjunction with onClientRender in order to display continuously.
Syntax
bool dxDrawPrimitive ( string pType, bool postGUI, table vertex1 [, table vertex2, ...] )
Required Arguments
- pType: Type of primitive to be drawn.
- postGUI: A bool representing whether the line should be drawn on top of or behind any ingame GUI (rendered by CEGUI).
- vertices: Tables representing each primitive vertex, required amount of them is determined by primitive type.
Allowed types
More info on primitives may be found on this MSDN site
- pointlist: Renders the vertices as a collection of isolated points.
- linelist: Renders the vertices as a list of isolated straight line segments.
- linestrip: Renders the vertices as a single polyline.
- trianglelist: Renders the specified vertices as a sequence of isolated triangles. Each group of three vertices defines a separate triangle.
- trianglestrip: Renders the vertices as a triangle strip.
- trianglefan: Renders the vertices as a triangle fan.
Vertices format
- posX: An float representing the absolute X position of the vertex, represented by pixels on the screen.
- posY: An float representing the absolute Y position of the vertex, represented by pixels on the screen.
- color (optional): An integer of the hex color, produced using tocolor or 0xAARRGGBB (AA = alpha, RR = red, GG = green, BB = blue). If it's not specified, white color is used.
Returns
Returns a true if the operation was successful, false otherwise.
Example
Click to collapse [-]
Example 1This is a small example that creates trianglefan primitive with vertices in places that user clicks. It assigns every vertex random color.
local vertices = {} function onClick(btn, state, x, y) if btn ~= "left" then return end if state ~= "up" then return end local vertex = {x, y, tocolor(math.random(255), math.random(255), math.random(255))} table.insert(vertices, vertex) end addEventHandler("onClientClick", root, onClick) function draw() dxDrawPrimitive("trianglefan", true, unpack(vertices)) end addEventHandler("onClientPreRender", root, draw)
Click to collapse [-]
Example 2This example draws one complete oscillation of a sine wave starting in the center of the players screen using a linestrip type primitive.
local screenSizeX,screenSizeY = guiGetScreenSize() -- save the current screen dimensions local sinCoords = {} function resStart() -- do all this once during "onClientResourceStart", rather than every frame local range = math.pi * 2 -- to get 1 complete oscillation of the sine wave we need the range from 0 to 2pi local resolution = 100 -- resolution in this example means in how many steps we draw the linestrip, higher resolution means smoother curve at the expense of longer computation time and higher memory usage local scale = 50 for i=0,range,range/resolution do -- "loop through this [resolution] times, starting at 0 and ending at [range]" local x = screenSizeX * 0.5 + i * scale -- start at the center of the screen and go from there local y = screenSizeY * 0.5 - math.sin(i) * scale -- subtract rather than add because greater y value means lower on the screen, which is the opposite of what we're used to seeing in graphs table.insert(sinCoords,{x,y}) end end addEventHandler("onClientResourceStart",getResourceRootElement(getThisResource()), resStart) function exampleRender() dxDrawPrimitive("linestrip",true,unpack(sinCoords)) -- render a linestrip type primitive with the coordinates we calculated earlier to draw our sine wave end addEventHandler("onClientRender",getRootElement(),exampleRender)
Click to expand [+]
Example 3See Also
- dxConvertPixels
- dxCreateFont
- dxCreateRenderTarget
- dxCreateScreenSource
- dxCreateShader
- dxCreateTexture
- dxDrawCircle
- dxDrawImage
- dxDrawImageSection
- dxDrawLine
- dxDrawLine3D
- dxDrawMaterialLine3D
- dxDrawMaterialPrimitive
- dxDrawMaterialPrimitive3D
- dxDrawMaterialSectionLine3D
- dxDrawPrimitive
- dxDrawPrimitive3D
- dxDrawRectangle
- dxDrawText
- dxDrawWiredSphere
- dxGetBlendMode
- dxGetFontHeight
- dxGetMaterialSize
- dxGetPixelColor
- dxGetPixelsSize
- dxGetPixelsFormat
- dxGetStatus
- dxGetTextSize
- dxGetTextWidth
- dxGetTexturePixels
- dxIsAspectRatioAdjustmentEnabled
- dxSetAspectRatioAdjustmentEnabled
- dxSetBlendMode
- dxSetPixelColor
- dxSetRenderTarget
- dxSetShaderValue
- dxSetShaderTessellation
- dxSetShaderTransform
- dxSetTestMode
- dxSetTextureEdge
- dxSetTexturePixels
- dxUpdateScreenSource