#Tardis Rendering

1 messages · Page 1 of 1 (latest)

kind mango
#

@orchid ice I'm going to put this in a thread to avoid clogging up other channels

#

I made a real basic and badly-written version of the Render Target-free idea I was talking about before

#
AddCSLuaFile()

ENT.Type = "anim"
ENT.Base = "base_gmodentity"
ENT.PrintName = "Rendering Test"
ENT.Category = "Test entities"
ENT.Spawnable = true

function ENT:Initialize()
    if SERVER then
        self:SetModel( "models/hunter/misc/lift2x2.mdl" )
        self:PhysicsInit( SOLID_VPHYSICS )
        self:SetMoveType( MOVETYPE_VPHYSICS )
        self:SetSolid( SOLID_VPHYSICS )
        local phys = self:GetPhysicsObject()
        if phys:IsValid() then
            phys:Wake()
        end
    end
end

if not CLIENT then return end

-- This is where we're pretending the tardis is in the world when the player is inside of it
local function GetFakeTardisPosAng()
    local time = CurTime()

    local pos = Vector( math.sin( time * 0.3 ) * 5, math.cos( time * 0.2 ) * 7, math.sin( time * 0.1 ) * 9 )
    local ang = Angle( math.sin( time * 0.1 ) * 10, math.cos( time * 0.2 ) * 20, math.sin( time * 0.3 ) * 30 )

    return pos, ang
end

-- Really low-quality and bad check for if the player is inside of the tardis
-- This also changes the render bounds of the entity so it calls the draw function in its fake location when the player is inside of it
function ENT:Think()
    if self:GetPos():Distance(LocalPlayer():GetPos()) > 75 then
        LocalPlayer().Tardis = nil
        self:SetRenderBounds( self:OBBMins(), self:OBBMaxs() )
    else
        LocalPlayer().Tardis = self
        local fakePos, fakeAng = GetFakeTardisPosAng()
        self:SetRenderBoundsWS( fakePos + self:OBBMins() * 2, fakePos + self:OBBMaxs() * 2 )
    end
end

function ENT:Draw()
    -- If the player is inside the tardis, render the tardis at its fake position/angles
    if IsValid( LocalPlayer().Tardis ) then
        local fakePos, fakeAng = GetFakeTardisPosAng()
        self:SetRenderOrigin( fakePos )
        self:SetRenderAngles( fakeAng )
    end

    self:DrawModel()

    -- Reset its offsets
    self:SetRenderOrigin()
    self:SetRenderAngles()
end

-- Move the camera to be relative to the tardis if the player is inside of it
hook.Add( "CalcView", "A1_RenderTest_MoveCamera", function( ply, pos, angles, fov )
    local view = {}
    view.origin = pos
    view.angles = angles
    view.fov = fov

    local tardis = ply.Tardis

    -- If we're not in the tardis, return the normal view
    if not IsValid( tardis ) then return view end

    -- Calculate the player's view relative to where the tardis actually is so
    local localPos = tardis:WorldToLocal( pos )
    local localAng = tardis:WorldToLocalAngles( angles )

    local fakePos, fakeAng = GetFakeTardisPosAng()

    -- Use the player's view relative to the tardis to calculate where the player's view should be relative to the fake tardis position/angle
    local adjustedPos, adjustedAng = LocalToWorld( localPos, localAng, fakePos, fakeAng )

    view.origin = adjustedPos
    view.angles = adjustedAng

    return view
end )

-- Move the viewmodel to be relative to the tardis if the player is inside of it
-- This is the same logic as CalcView with slightly different formatting
hook.Add( "CalcViewModelView", "A1_RenderTest_MoveViewmodel", function( wep, vm, oldPos, oldAng, actualPos, actualAng )
    local tardis = LocalPlayer().Tardis
    if not IsValid( tardis ) then return end

    local localPos = tardis:WorldToLocal( actualPos )
    local localAng = tardis:WorldToLocalAngles( actualAng )

    local fakePos, fakeAng = GetFakeTardisPosAng()

    local adjustedPos, adjustedAng = LocalToWorld( localPos, localAng, fakePos, fakeAng )

    return adjustedPos, adjustedAng
end )
#

This is, of course, much less complicated than an actual implementation of this idea would need to be in order to actually be used for your project, but I hope it gets the idea across

orchid ice
#

what does this actually do i cant follow

#

it still looks like youre teleporting

kind mango
#

The player and the tardis don't actually move

#

I'm using the CalcView and CalcViewModelView hooks to move where the player's camera is while they're inside the tardis

#

I'm also using ENT:SetRenderOrigin and ENT:SetRenderAngles to move where the tardis's interior (And exterior in this example, but your usage would be different) renders while the player is inside of the tardis

#

They're both "pretending" to be far away from where they actually are

orchid ice
#

so the actual player is still inside the mirror room?

kind mango
#

Yep

#

There's no SetPos() anywhere in here

#

It's all just rendering trickery

orchid ice
#

but wouldnt the skybox still be unrendered youre far enough away or looking in the wrong direction

#

like the real tardis entity also just places a seperate interior model somewhere on the map, i could literally place it into the mirror room aswell

kind mango
#

As far as the game's rendering system is concerned, the player IS standing above ground, so the skybox should render as normal

#

You can see that fact with the lighting here

orchid ice
kind mango
#

Which is something we can all enjoy

orchid ice
# kind mango

so what it does differently to render targets is that there's no portal, it literally moves where your view is?

kind mango
#

Correct

orchid ice
#

so that means the interior model also has to physically be there?

kind mango
#

Physically? No. Visually? Yes.

#

I should mention that this strategy of moving the camera around in tricky ways to make it look like you're positioned somewhere you aren't is actually how Portal's portals work

orchid ice
#

since each control element is a seperate entity, its not all one model

kind mango
#

You can have as many of those as you want

#

In the code above I'm using the per-entity ENT:SetRenderOrigin function, but there are other methods for doing the same to multiple models

#

I should clarify briefly that I'm not necessarily trying to tell you that this change is worth the amount of time and work it would take to implement it.

I really don't know how much effort that would take to do, practically.
I'm just trying to make you aware of something that would solve some of the issues you seem to be running into

#

Whether that solution is worth the time and effort is up to you

orchid ice
#

im not concerned with the time and effort honestly..

#

my concern is that i dont have the actual skill to do any of this

#

i still cant figure out how to fix basic rendering issues, let alone rewrite the entire addon's rendering core

kind mango
#

If you don't mind a suggestion on that front: I would really recommend doing the learning part and the implementing part as separate steps.

Don't try to learn something new while also trying to use that new thing to implement a change or fix to your project.
Instead, learn that new thing totally separately from your project and—Once you understand that new topic pretty well from experimenting—apply it to your project

#

Doing both at once can be daunting and it can lead to a bit of a code mess if you're not careful and lucky