Hello all,
This time not a quetsion, but a problem with an if block I recently added to VC2 lights rendering. All the script is client side, I just want to know if the player cann see the light which is being rendered, and then cancels the rendering if the player can't see this light.
So well many problems : first util.PxelVisible does not return a boolean so i made a wrokaround you'll see it, second that works but only when you've got a special fixed angle, so by the way a player is not stating neither a vehicle, so that's a real problem.
[code]
local lightMat = Material("sprites/light_ignorez")
local handle = util.GetPixelVisibleHandle()
local function DrawVehicleLights(entity, vehTbl, type)
local dist = LocalPlayer():GetPos():Distance(entity:GetPos())
if (dist > 1500) then return end
if (type == 0) then
for _, v in pairs(vehTbl.lights) do
local pos = entity:LocalToWorld(v)
--I also tried to create the PxVisHandle here but still no luck.
if (util.PixelVisible(pos, 1500, handle) == 0) then continue end
render.SetMaterial(lightMat)
render.DrawSprite(pos, 16, 16, Color(255, 255, 0, 255))
end
end
end
[/code]
In the hope of a quick answer,
Thanks by advance,
Yuri6037
You must create a new handle for each light on each vehicle.
[QUOTE=Robotboy655;47891836]You must create a new handle for each light on each vehicle.[/QUOTE]
However I already tried that same result... Read the comment I put on my code. I also tried to GetPixVisHandle in the for loop, but it hasn't changed things...
You must create a single handle for every single sprite/light. You cannot keep recreating them in a loop over and over again, you cannot create only one and reuse it.
Once handle. Per one sprite/light. Cache them.
I did this before, I know how it works.
[QUOTE=Robotboy655;47897057]You must create a single handle for every single sprite/light. You cannot keep recreating them in a loop over and over again, you cannot create only one and reuse it.
Once handle. Per one sprite/light. Cache them.
I did this before, I know how it works.[/QUOTE]
You asked me to create one for each lights, then you're saying i can't create it in loop and i can't create it once, then this makes oposite sence !?
[QUOTE=Yuri6037;47899275]You asked me to create one for each lights, then you're saying i can't create it in loop and i can't create it once, then this makes oposite sence !?[/QUOTE]
You must create only ONE HANDLE PER ONE LIGHT. Not multiple handles per one light (creating a new one in a loop/hook every frame for each light) or one handle per multiple lights(creating one outside of hooks or loops).
CACHE YOUR HANDLES!
Like so? Psuedo code
[code]
for i = 1, 10 do
tbl[i] = createLight()
end
[/code]
[QUOTE=Robotboy655;47899323]You must create only ONE HANDLE PER ONE LIGHT. Not multiple handles per one light (creating a new one in a loop/hook every frame for each light) or one handle per multiple lights(creating one outside of hooks or loops).
CACHE YOUR HANDLES![/QUOTE]
Wow ok, but it remains a bit complicated by the fact lua does not respect any order in tables.....
[QUOTE=Yuri6037;47899445]Wow ok, but it remains a bit complicated by the fact lua does not respect any order in tables.....[/QUOTE]
what are you talking about
[QUOTE=Yuri6037;47899445]Wow ok, but it remains a bit complicated by the fact lua does not respect any order in tables.....[/QUOTE]
THe only thing that's not ordered is non-numeric keys when iterated with next()
[QUOTE=Noi;47898064]Is PixVis cheaper than trace?[/QUOTE]
To answer this, I honestly have no idea, but PixVis is specifically made for this purpose.
So I'll try an implementation of caching, I'll tell if it works.
[editline]8th June 2015[/editline]
Well caching is not working but this time not at all ! Even in the fixed angle it's not working. The lights are always invisible !!!!
[code]
local cache0 = {} //Left blinkers
local function DrawVehicleLights(entity, vehTbl, type)
local dist = LocalPlayer():GetPos():Distance(entity:GetPos())
if (dist > 1500) then return end
if (type == 0) then
for k, v in pairs(vehTbl.leftBlinkers) do
local handle = cache0[k]
if (handle == nil) then
handle = util.GetPixelVisibleHandle()
cache0[k] = handle
end
local pos = entity:LocalToWorld(v)
if (util.PixelVisible(pos, 1500, handle) == 0) then continue end
render.SetMaterial(lightMat)
render.DrawSprite(pos, 16, 16, Color(255, 255, 0, 255))
end
end
end
[/code]
Anyone ?
[editline]8th June 2015[/editline]
Still nobody, where are you robotboy ? I tried your solution but now no lights are rendered.
I think you pissed him off
That will be a problem because I absolutely need this to work for the next version of my GameMode...
If you want help, don't be a prick basically - noone is going to want to help someone who is rude
[editline]8th June 2015[/editline]
However, I see nothing wrong with your code you posted above. Make sure that your logic is working by adding some debug prints for example. Also, where are you calling this? It'll need to be in a draw hook such as PostDrawTranslucentRenderables
It's called each frames on PostDrawTranslucentRenderables.
Basicaly the PostDrawTranslucentRenderables hook will iterate over every enetities chack vehicles in the map, check if a table is attached to specific meta variable, if no then check if has data in a separate big table, if so then set this separated table to a meta variable into that entity for future quick access (removes one of the 2 for loops for optimisation).
And when all these logics passed, it checks if the vehicle has different lights activated (GetNWBool).
Then if indeed one of the GetNWBools is true, then call ths function to draw the light type defined by NWBool...
Actually still nobody maybe it's time to post this on GMod issues...
Robot boy ? Any idea ?
I can't update the GameMode without this...
Bump
Bump
when the vehicle spawns, you need to create individual pixel handles for each light you want to render. store them as a variable in the entity so you can use them later. then in the draw lights function, retrieve the handles from the entity with the variables you stored on its creation. should be easy from then on.
here's an example
[lua]
function ENT:Initialize()
self.PixelHandle1 = util.GetPixelVisibleHandle()
self.PixelHandle2 = util.GetPixelVisibleHandle()
self.PixelHandle3 = util.GetPixelVisibleHandle()
...
//rest of your code here
end
function DrawVehicleLights( entity, vehTbl, type )
local handle1 = util.PixelVisible( pos, radius, self.PixelHandle1 )
local handle2 = util.PixelVisible( pos, radius, self.PixelHandle2 )
local handle3 = util.PixelVisible( pos, radius, self.PixelHandle3 )
...
//rest of your code here
end
[/lua]
if the number of lights varies, then you probably want to set a maximum amount of lights and create that many handles. then in the drawing function, use one of them. it's ok if you don't use all of them.
[QUOTE=Yuri6037;47904155]So I'll try an implementation of caching, I'll tell if it works.
[editline]8th June 2015[/editline]
Well caching is not working but this time not at all ! Even in the fixed angle it's not working. The lights are always invisible !!!!
[code]
local cache0 = {} //Left blinkers
local function DrawVehicleLights(entity, vehTbl, type)
local dist = LocalPlayer():GetPos():Distance(entity:GetPos())
if (dist > 1500) then return end
if (type == 0) then
for k, v in pairs(vehTbl.leftBlinkers) do
local handle = cache0[k]
if (handle == nil) then
handle = util.GetPixelVisibleHandle()
cache0[k] = handle
end
local pos = entity:LocalToWorld(v)
if (util.PixelVisible(pos, 1500, handle) == 0) then continue end
render.SetMaterial(lightMat)
render.DrawSprite(pos, 16, 16, Color(255, 255, 0, 255))
end
end
end
[/code][/QUOTE]
You must cache them per vehicle, as I said, you cannot cache them in a global table.
You [b][highlight]CANNOT REUSE THEM[/highlight][/b]. How is that not clear?
( eg. cache them in on the vehicle entity )
For example:
You have 2 vehicles spawned, each vehicle has 4 lights.
That is 8 unique handles.
You spawn 1 more vehicle with 4 ligthts. That is 4 new unique handles.
You delete all vehicles and spawn a new one.
What you do:
* Reuse the handles from first spawned vehicle
What you SHOULD be doing:
* Create 4 new unique handles
[QUOTE=Robotboy655;47947861]You must cache them per vehicle, as I said, you cannot cache them in a global table.
You [b][highlight]CANNOT REUSE THEM[/highlight][/b]. How is that not clear?
( eg. cache them in on the vehicle entity )
For example:
You have 2 vehicles spawned, each vehicle has 4 lights.
That is 8 unique handles.
You spawn 1 more vehicle with 4 ligthts. That is 4 new unique handles.
You delete all vehicles and spawn a new one.
What you do:
* Reuse the handles from first spawned vehicle
What you SHOULD be doing:
* Create 4 new unique handles[/QUOTE]
Wow what you're asking is much more complicated due to the fact i have not the ENT table, not any function called client side when vehicle spawns...
Well, I'll try to see what I can do to store caches per vehicles. So that means I need one PixVis for one render.DrawSprite !
[editline]13th June 2015[/editline]
Well That's still not working... I get exactly the same problem.
Sorry Robotboy your idea has not changed anything. It's still returning always 0...
[code]
//The hook to create the caches
hook.Add("PostDrawTranslucentRenderables", "VC_LightsRenderer", function()
for _, v in pairs(ents.GetAll()) do
if (IsValid(v) and v:IsVehicle() and VC2:CanVehicleHaveData(v)) then
if (v:GetNWString("Name", nil) != nil) then
if (v.VehicleTable == nil or v.VehicleTable == "" or v.VehicleTable.VC2 == nil) then
v.VehicleTable = {}
v.VehicleTable.Name = v:GetNWString("Name")
v.VehicleTable.VC2 = VC2:GetVehicleByName(v:GetNWString("Name"))
v.VehicleTable.Caches = {
leftBlinks = {},
rightBlinks = {},
fronts = {},
backs = {},
heads = {},
roads = {},
brakes = {}
end
end
end
end
end
end)
//The code which draws them...
local lightMat = Material("sprites/light_ignorez")
local function DrawVehicleLights(entity, vehTbl, type)
local dist = LocalPlayer():GetPos():Distance(entity:GetPos())
if (dist > 1500) then return end
if (type == 0) then
for k, v in pairs(vehTbl.leftBlinkers) do
local handle = entity.VehicleTable.Caches.leftBlinks[k]
if (handle == nil) then
handle = util.GetPixelVisibleHandle()
entity.VehicleTable.Caches.leftBlinks[k] = handle
end
local pos = entity:LocalToWorld(v)
if (util.PixelVisible(pos, 1500, handle) == 0) then continue end
render.SetMaterial(lightMat)
render.DrawSprite(pos, 16, 16, Color(255, 255, 0, 255))
end
end
end
[/code]
Your second argument in util.PixelVisible is huge, me and the default lamp tool use 4. You have 1500.
Do you mean this is the argument that causes the function to return always 0 ?! Well if that's true then the function is useless... 1500 isn't huge it's realism that's all...
[QUOTE=Yuri6037;47949337]Do you mean this is the argument that causes the function to return always 0 ?! Well if that's true then the function is useless... 1500 isn't huge it's realism that's all...[/QUOTE]
Do you realize what 1500 is? You are making your light like 1500 unis in radius. Unless your vehicles are all this thing:
[img]http://i.imgur.com/hZ3QwRp.png[/img]
I suggest you lower it to to like 8 or 4.
Or if you don't want my help, then just keep whining and I will stop wasting my time helping you.
[QUOTE=Robotboy655;47949529]Do you realize what 1500 is? You are making your light like 1500 unis in radius. Unless your vehicles are all this thing:
[img]http://i.imgur.com/hZ3QwRp.png[/img]
I suggest you lower it to to like 8 or 4.
Or if you don't want my help, then just keep whining and I will stop wasting my time helping you.[/QUOTE]
Hey ! I never refused your help. I'm just saying that 1500 is defined to be sure you can see vehicle lights. The 1500 is based on the fact human models when you're near them you're over 100 units near them.
this is how pixelvisible works. if anything that is able to overlap the vector you plug in as the position is within the radius in screen [b]pixels[/b], it will start decreasing from 1 to 0. if it isn't visible at all, it will return 0.
this should help a lot.
[img]http://i.imgur.com/vEOWEdy.png[/img]
[img]http://i.imgur.com/PQhXzU8.png[/img]
[img]http://i.imgur.com/8Yqafhi.png[/img]
and of course, anything behind the vector relative to your view's origin will not affect the function.
when you put in 1500 pixels as the radius, unless you have a 3000 pixel wide game resolution, you will never see the light at its fullest. as robotboy said, i recommend 4 or 8 pixels as a radius.
also, just to point out, you should create the pixel handle when the entity is created. checking if it doesn't exist and [i]then[/i] creating one is kinda hacky and i don't recommend it.
[QUOTE=Yuri6037;47949822]Hey ! I never refused your help. I'm just saying that 1500 is defined to be sure you can see vehicle lights. The 1500 is based on the fact human models when you're near them you're over 100 units near them.[/QUOTE]
Is this how you see vehicles in your "on the fact human models", in your "real world"?
[img]http://i.imgur.com/ckiEst0.png[/img]
Sorry, you need to Log In to post a reply to this thread.