A module that simplifes the way VPF are handled in Roblox, allows to show models, and manipulate them inside the VPF, while keeping performances good.
An example on how to use it can be found at the very bottom.
- You will need to get the "spring" module from BlackShibe and place it as a child of the ModuleScript.
local viewer = VPFViewer.new(player, vpf)
viewer:Init()
viewer:LockAxis(x_locked, y_locked)
Parameter | Type | Description |
---|---|---|
x_locked |
Boolean |
Optional. Whether the x-axis is locked during object's rotation |
y_locked |
Boolean |
Optional. Whether the y-axis is locked during object's rotation |
:CacheModels allows to cache given models before being shown on the VPF, to avoid loading times / issues and improve performances or large models.
VPFViewer:CacheModels(RS.Models:GetChildren())
Parameter | Type | Description |
---|---|---|
Models |
Array : {[any] : Model} |
Required. The array of models to cache before display on VPF |
VPFViewer:CleanCache()
VPFViewer:ShowModel("Model1")
Parameter | Type | Description |
---|---|---|
Model |
string / Instance |
Required. Model or Model's name (if in cache) to show on the VPF |
VPFViewer:SetMultiplier(2) -- Twice as far as the maximum
Parameter | Type | Description |
---|---|---|
Value |
number |
Optional. Multiplier of the distance between the model and the camera, defaults to 1 |
VPFViewer:SetSensitivity(10) -- Speed will be slowed by a factor of 10
Parameter | Type | Description |
---|---|---|
Value |
number |
Optional. How sensitive the 3D model will move relative to the mouse movement. The lower the value is, the faster it will move |
VPFViewer:Destroy()
local RS = game:GetService("ReplicatedStorage")
local players = game:GetService("Players")
local p = players.LocalPlayer
local vpf = p.PlayerGui:WaitForChild("ViewportUI").ViewportFrame
local parts = RS.Parts
local Module = require(script.VPFViewer)
local Viewer = Module.new(p, p.PlayerGui:WaitForChild("ViewportUI").ViewportFrame)
Viewer:Init() -- ALWAYS INIT BEFORE ANY USE
Viewer:CacheModels(parts:GetChildren())
Viewer:LockAxis(false, false) -- Free Rotation on X and Y axis
local currentModel = parts.Car
local index = 1
game.UserInputService.InputBegan:Connect(function(inputObject)
if inputObject.KeyCode == Enum.KeyCode.X then
Viewer:ShowModel(currentModel)
index = math.fmod(index, #parts:GetChildren()) + 1 -- Loop through all models, and goes back to 1 once hit the last (remain of the euclidian division of i / #p)
currentModel = parts:GetChildren()[index]
end
end)
I'm just going to go over the maths calculations for the camera and the model's rotation.
We need to find the "depth" or distance between the camera and the model so that it perfectly fits inside the camera. For this we can take a look at the FOV and how it works to display models on screen (ignore the drawing skills pls)
We have a right triangle problem! We need to find the distance, here noted d, if you remember your math classes you know that tan(θ) = opposite side / adjacent side So we just want the adjacent side, we have:
- adjacent = opposite / tan(θ). But here we see that the angle we want is half of the FOV, so :
- adjacent = opposite / tan(fov / 2) <=> distance = radius / tan(math.rad(fov / 2))