@rbxts/viewportmodel
v1.0.2
Published
Type script version of the EgoMoose module "ViewportModel.lua". It's a module calculating the camera position to fit a model in the viewport frame.
Readme
ViewportModel.ts
ViewportModel.ts is a TypeScript version of the EgoMoose module ViewportModel.lua. It calculates the camera position to fit a model in the viewport frame.
The original Lua module can be found here: Github: EgoMoose/ViewportModel.lua
You can also find the Roblox Devforum post here: Devforum: ViewportFrame Model Fitter
Quick Start
Install
To install the module, you can use npm:
npm i @rbxts/viewportmodelUsage
// Setup viewport frame and camera
const viewportFrame = PATH_TO_VIEWPORT_FRAME;
const camera = new Instance("Camera");
viewportFrame.CurrentCamera = camera;
const inst = MODEL_TEMPLATE:Clone();
inst.Parent = viewportFrame;
// Setup the ViewportModel
const viewportModel = new ViewportModel(viewportFrame, camera);
viewportModel.setModel(inst);
// Make the camera fit the model with the desired orientation
const angle = CFrame.fromEulerAnglesYXZ(-math.pi * 0.05, -math.pi * 0.2, 0);
const cf = viewportModel.getMinimumFitCFrame(angle);
camera.CFrame = cf;Documentation
Constructor
Create a new ViewportModel instance using the constructor:
new (vpf: ViewportFrame, camera: Camera): ViewportModel;Parameters:
vpf: TheViewportFrameto use for rendering the model.camera: TheCamerato use for rendering the model. This camera should be set to theViewportFrameCurrentCameraproperty.
Methods
setModel
Used to set the model that is being focused on. Should be used for new models and/or a change in the current model.
e.g. parts added/removed from the model or the model cframe changed
setModel(model: Model): void;Parameters:
model: TheModelto set. This should be the model that you want to fit in the viewport frame.
calibrate
Should be called when something about the viewport frame / camera changes
e.g. the frame size or the camera field of view
calibrate(): void;getFitDistance
Returns a fixed distance that is guaranteed to encapsulate the full model This is useful for when you want to rotate freely around an object w/o expensive calculations Focus position can be used to set the origin of where the camera's looking Otherwise the model's center is assumed
getFitDistance(focusPosition?: Vector3): number;Parameters:
focusPosition: Optional. The position to focus on. If not provided, the model's center will be used.
getMinimumFitCFrame
Returns the optimal camera cframe that would be needed to best fit the model in the viewport frame at the given orientation. Keep in mind this functions best when the model's point-cloud is correct as such models that rely heavily on meshes, csg, etc will only return an accurate result as their point cloud
getMinimumFitCFrame(orientation: CFrame): CFrame;Parameters:
orientation: The orientation to use for the camera. This should be aCFramerepresenting the desired orientation of the camera.
Examples
Fixed Minimum Distance with rotating camera
The first example is to calculate a fixed minimum distance that’s guaranteed to contain the model regardless of the camera orientation or viewport size.
// Setup viewport frame and camera
const viewportFrame = PATH_TO_VIEWPORT_FRAME;
const camera = new Instance("Camera");
viewportFrame.CurrentCamera = camera;
const inst = MODEL_TEMPLATE:Clone();
inst.Parent = viewportFrame;
// Setup the ViewportModel
const viewportModel = new ViewportModel(viewportFrame, camera);
viewportModel.setModel(inst);
// Make the camera rotating while fitting the model
const distance = viewportModel.getFitDistance();
RunService.RenderStepped:Connect(() => {
// Update the camera CFrame
camera.CFrame = cf.mul(CFrame.fromEulerAnglesYXZ(math.rad(-20), math.rad(tick() * 20) % (math.pi * 2), 0).mul(CFrame.new(0, 0, distance)));
});Minimum Fit in every Orientation while camera is rotating
The second example is to calculate a camera cframe that best fits the model given an orientation. This will mean that the model will always be touching at least one edge of the viewport frame.
However, it’s important to note that this calculation is based off of the model’s point cloud meaning meshes, csg, and/or any other base part that makes it difficult to get a proper point cloud may cause this calculation to seem inaccurate.
// Setup viewport frame and camera
const viewportFrame = PATH_TO_VIEWPORT_FRAME;
const camera = new Instance("Camera");
viewportFrame.CurrentCamera = camera;
const inst = MODEL_TEMPLATE:Clone();
inst.Parent = viewportFrame;
// Setup the ViewportModel
const viewportModel = new ViewportModel(viewportFrame, camera);
viewportModel.setModel(inst);
// Make the camera rotating while fitting the model
RunService.RenderStepped:Connect(() => {
const orientation = CFrame.fromEulerAnglesYXZ(math.rad(-20), math.rad(tick() * 20) % (math.pi * 2), 0);
const cf = viewportModel.getMinimumFitCFrame(orientation);
camera.CFrame = cf
});