Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --Converted with ttyyuu12345's model to script plugin v4
- function sandbox(var,func)
- local env = getfenv(func)
- local newenv = setmetatable({},{
- __index = function(self,k)
- if k=="script" then
- return var
- else
- return env[k]
- end
- end,
- })
- setfenv(func,newenv)
- return func
- end
- cors = {}
- mas = Instance.new("Model",game.StarterPlayer.StarterCharacterScripts)
- LocalScript0 = Instance.new("LocalScript")
- SelectionBox1 = Instance.new("SelectionBox")
- ModuleScript2 = Instance.new("ModuleScript")
- ModuleScript3 = Instance.new("ModuleScript")
- ModuleScript4 = Instance.new("ModuleScript")
- ModuleScript5 = Instance.new("ModuleScript")
- ModuleScript6 = Instance.new("ModuleScript")
- LocalScript0.Name = "Tutorial"
- LocalScript0.Parent = mas
- table.insert(cors,sandbox(LocalScript0,function()
- local p = game:GetService("Players").LocalPlayer
- local m = p:GetMouse()
- local cam = workspace.CurrentCamera
- local selObj = nil
- local camCframe = nil
- local oS = nil
- local coolnessOffset = Vector3.new()
- local function canMove(ob)
- return ob.Name == "Object"
- end
- local function getCP(r, p)
- local rO, D = r.Origin - p, r.Direction
- return rO - ( rO:Dot(D)/D:Dot(D) ) * D
- end
- local function angleBetween(v1, v2)
- return math.acos(v1:Dot(v2)/(v1.magnitude * v2.magnitude))
- end
- local e = game:GetService("ReplicatedStorage").UpdPhys
- local rr = require(script:WaitForChild("RotatedRegion3"))
- m.Button1Down:Connect(function()
- if m.Target and canMove(m.Target) then
- m.Target.CanCollide = false
- camCframe = cam.CFrame:ToObjectSpace(m.Target.CFrame)
- oS = m.Target.Size
- coolnessOffset = -getCP(m.UnitRay, m.Target.Position)
- e:FireServer(m.Target)
- m.Target.Anchored = true
- m.Target.Velocity = Vector3.new()
- m.Target.RotVelocity = Vector3.new()
- selObj = m.Target
- end
- end)
- m.Button1Up:Connect(function()
- if selObj then
- selObj.Anchored = false
- selObj.CanCollide = true
- end
- selObj = nil
- end)
- game:GetService("RunService").RenderStepped:Connect(function(dt)
- coolnessOffset = coolnessOffset:Lerp(Vector3.new(), 0.2)
- end)
- game:GetService("RunService").RenderStepped:Connect(function(dt)
- if selObj then
- selObj.CFrame = cam.CFrame:ToWorldSpace(camCframe)
- local ray = Ray.new(cam.CFrame.p, cam.CFrame.LookVector * 1000)
- local _, p, n = workspace:FindPartOnRayWithIgnoreList(ray, {script.Parent, selObj})
- local dist = ((cam.CFrame.p - p).magnitude - selObj.Size.magnitude / 2) * -math.cos(angleBetween(ray.Direction, n))
- selObj.Size = (oS * dist / camCframe.p.magnitude)
- selObj.Position = cam.CFrame.p + cam.CFrame.LookVector * dist
- for i = 1, 0, -0.01 do
- local R = rr.fromPart(selObj)
- if #R:cast({script.Parent, selObj}, 1) > 0 then
- dist = dist * i
- selObj.Size = (oS * dist / camCframe.p.magnitude)
- selObj.Position = cam.CFrame.p + cam.CFrame.LookVector * dist
- else
- break
- end
- end
- selObj.Position = selObj.Position + coolnessOffset
- end
- end)
- end))
- SelectionBox1.Parent = LocalScript0
- SelectionBox1.Visible = false
- SelectionBox1.Color = BrickColor.new("Institutional white")
- SelectionBox1.Color3 = Color3.new(1, 1, 1)
- SelectionBox1.LineThickness = 0.009999999776482582
- SelectionBox1.SurfaceColor = BrickColor.new("Really black")
- SelectionBox1.SurfaceColor3 = Color3.new(0, 0, 0)
- ModuleScript2.Name = "RotatedRegion3"
- ModuleScript2.Parent = LocalScript0
- table.insert(cors,sandbox(ModuleScript2,function()
- --[[
- This rotated region3 module is a bit different than the one I previously wrote. This uses GJK to do the collision calculations and
- as such does not calculate the minimum translation vector. In addition it does not calculate the intersection points anymore either.
- I don't think that had much place in a rotated region3 module.
- As far as new features the module now supports a vast array of shapes and point clouds meaning more accurate collision!
- API:
- Constructors:
- region.new(cframe, size)
- > Creates a region from a cframe which acts as the center of the region and size which extends to
- > the corners like a block part.
- region.block(cframe, size)
- > This is the exact same as the region.new constructor, but has a different name.
- region.wedge(cframe, size)
- > Creates a region from a cframe which acts as the center of the region and size which extends to
- > the corners like a wedge part.
- region.cornerWedge(cframe, size)
- > Creates a region from a cframe which acts as the center of the region and size which extends to
- > the corners like a cornerWedge part.
- region.cylinder(cframe, size)
- > Creates a region from a cframe which acts as the center of the region and size which extends to
- > the corners like a cylinder part.
- region.ellipsoid(cframe, size)
- > Creates a region from a cframe which acts as the center of the region and size which extends to
- > the corners like a ball part.
- region.pointCloud(cloud)
- > Creates a region from a table of points. The region is treated as a convex 3D shape when doing the collision detections.
- region.fromPart(part)
- > Creates a region from a part in the game. It can be used on any base part, but the region
- > will treat unknown shapes (meshes, unions, etc) as block shapes.
- Methods:
- region:cast(ignore instance or table (descendants as well), int maxParts)
- > returns a table full of parts that are inside the region
- region:castPart(basePart)
- > returns a boolean as to whether or not a given part is within a region or not
- region:castPoint(vector3)
- > returns a boolean as to whether or not a given point is within a region or not
- Properties:
- region.CFrame
- > cframe that represents the center of the region
- region.Size
- > vector3 that represents the size of the region
- --]]
- local gjk = require(script:WaitForChild("gjk"));
- local support = require(script:WaitForChild("supports"));
- local vertices = require(script:WaitForChild("vertices"));
- local draw = require(script:WaitForChild("draw"));
- local region3 = {};
- local region3_mt = {__index = region3};
- -- private functions
- local type = type;
- local unpack = unpack;
- local insert = table.insert;
- local R3 = Region3.new;
- local v3 = Vector3.new;
- local function centroid(t)
- local sum = t[1] - t[1];
- for i = 1, #t do sum = sum + t[i]; end;
- return sum / #t;
- end;
- local function classify(part)
- if (part.ClassName == "Part") then
- if (part.Shape == Enum.PartType.Block) then
- return region3.block(part.CFrame, part.Size);
- elseif (part.Shape == Enum.PartType.Cylinder) then
- return region3.cylinder(part.CFrame, part.Size);
- elseif (part.Shape == Enum.PartType.Ball) then
- return region3.ellipsoid(part.CFrame, part.Size);
- end;
- elseif (part.ClassName == "WedgePart") then
- return region3.wedge(part.CFrame, part.Size);
- elseif (part.ClassName == "CornerWedgePart") then
- return region3.cornerWedge(part.CFrame, part.Size);
- elseif (part:IsA("BasePart")) then -- mesh, CSG, truss, etc... just use block
- return region3.block(part.CFrame, part.Size);
- end;
- end;
- -- public static functions
- function region3.new(cf, size)
- local self = {};
- self.CFrame = cf;
- self.Size = size;
- self.input = {vertices.block(cf, size * 0.5, {})};
- self.support = support.pointCloud;
- self.centroid = cf.p;
- return setmetatable(self, region3_mt);
- end;
- region3.block = region3.new;
- function region3.wedge(cf, size)
- local self = {};
- self.CFrame = cf;
- self.Size = size;
- self.input = {vertices.wedge(cf, size * 0.5, {})};
- self.support = support.pointCloud;
- self.centroid = centroid(self.input[1]);
- return setmetatable(self, region3_mt);
- end;
- function region3.cornerWedge(cf, size)
- local self = {};
- self.CFrame = cf;
- self.Size = size;
- self.input = {vertices.cornerWedge(cf, size * 0.5, {})};
- self.support = support.pointCloud;
- self.centroid = centroid(self.input[1]);
- return setmetatable(self, region3_mt);
- end;
- function region3.cylinder(cf, size)
- local self = {};
- self.CFrame = cf;
- self.Size = size;
- self.input = {cf, size * 0.5};
- self.support = support.cylinder;
- self.centroid = cf.p;
- return setmetatable(self, region3_mt);
- end;
- function region3.ellipsoid(cf, size)
- local self = {};
- self.CFrame = cf;
- self.Size = size;
- self.input = {cf, size * 0.5};
- self.support = support.ellipsoid;
- self.centroid = cf.p;
- return setmetatable(self, region3_mt);
- end;
- function region3.pointCloud(cloud)
- local self = {};
- self.CFrame = CFrame.new(centroid(cloud));
- self.Size = v3();
- self.input = cloud;
- self.support = support.pointCloud;
- self.centroid = self.CFrame.p;
- return setmetatable(self, region3_mt);
- end;
- function region3.fromPart(part)
- return classify(part);
- end;
- -- public methods
- function region3:castPoint(point)
- local direction = self.centroid - point;
- return gjk(self.input, {point}, self.support, support.point, direction);
- end;
- function region3:castPart(part)
- local against = classify(part);
- local direction = self.centroid - against.centroid;
- return gjk(self.input, against.input, self.support, against.support, direction);
- end;
- function region3:cast(ignore, maxParts)
- local ignore = type(ignore) == "table" and ignore or {ignore};
- local maxParts = maxParts or 20;
- local min, max = {}, {};
- for _, enum in next, {Enum.NormalId.Right, Enum.NormalId.Top, Enum.NormalId.Back} do
- local direction = Vector3.FromNormalId(enum);
- insert(min, self.support(-direction, unpack(self.input)));
- insert(max, self.support(direction, unpack(self.input)));
- end;
- min, max = v3(min[1].x, min[2].y, min[3].z), v3(max[1].x, max[2].y, max[3].z);
- local allignedR3 = R3(min, max);
- local parts = game.Workspace:FindPartsInRegion3WithIgnoreList(allignedR3, ignore, maxParts);
- -- debug stuff
- --game.Workspace.CurrentCamera:ClearAllChildren();
- --draw.line(min, max, game.Workspace.CurrentCamera);
- local inRegion = {};
- for i = 1, #parts do
- local part = parts[i];
- if (self:castPart(part)) then
- insert(inRegion, part);
- end;
- end;
- return inRegion;
- end;
- -- return module
- return region3;
- end))
- ModuleScript3.Name = "gjk"
- ModuleScript3.Parent = ModuleScript2
- table.insert(cors,sandbox(ModuleScript3,function()
- local v3 = Vector3.new;
- local dot = v3().Dot;
- local cross = v3().Cross;
- local unpack = unpack;
- local insert = table.insert;
- local remove = table.remove;
- local function tripleProduct(a, b, c)
- -- (a x b) x c = b * (c . a) - a * (c . b)
- return b * dot(c, a) - a * dot(c, b);
- end;
- local function containsOrigin(simplex, direction)
- local a = simplex[#simplex];
- local a0 = -a;
- if (#simplex == 4) then
- local b, c, d = simplex[3], simplex[2], simplex[1];
- local ba, ca, da = b - a, c - a, d - a;
- local abc = cross(ba, ca);
- local adb = cross(da, ba);
- local acd = cross(ca, da);
- abc = dot(abc, da) > 0 and -abc or abc;
- adb = dot(adb, ca) > 0 and -adb or adb;
- acd = dot(acd, ba) > 0 and -acd or acd;
- if (dot(abc, a0) > 0) then
- remove(simplex, 1);
- direction = abc;
- elseif (dot(adb, a0) > 0) then
- remove(simplex, 2);
- direction = adb;
- elseif (dot(acd, a0) > 0) then
- remove(simplex, 3);
- direction = acd;
- else
- return true;
- end;
- elseif (#simplex == 3) then
- local b, c = simplex[2], simplex[1];
- local ba, ca = b - a, c - a;
- local baPerp, caPerp = tripleProduct(ca, ba, ba), tripleProduct(ba, ca, ca);
- if (dot(baPerp, a0) > 0) then
- remove(simplex, 1);
- direction = baPerp;
- elseif (dot(caPerp, a0) > 0) then
- remove(simplex, 2);
- direction = caPerp;
- else
- local abc = ba:Cross(ca);
- if (dot(abc, a0) == 0) then return true; end;
- direction = (dot(abc, a0) > 0) and abc or -abc;
- end;
- else
- local b = simplex[1];
- local ba = b - a;
- direction = tripleProduct(ba, a0, ba);
- end;
- return false, direction;
- end;
- local function collision(A, B, supportA, supportB, direction)
- local simplex = {supportA(direction, unpack(A)) - supportB(-direction, unpack(B))};
- direction = -direction;
- while (true) do
- insert(simplex, supportA(direction, unpack(A)) - supportB(-direction, unpack(B)));
- if (dot(simplex[#simplex], direction) < 0) then
- return false;
- else
- local pass, newDirection = containsOrigin(simplex, direction);
- if (pass) then return true; end;
- direction = newDirection;
- end;
- end;
- end;
- return collision;
- end))
- ModuleScript4.Name = "supports"
- ModuleScript4.Parent = ModuleScript2
- table.insert(cors,sandbox(ModuleScript4,function()
- -- support functions for GJK
- -- Ego
- local v3 = Vector3.new;
- local dot = v3().Dot;
- local cos = math.cos;
- local sin = math.sin;
- local min = math.min;
- local abs = math.abs;
- local huge = math.huge;
- local sqrt = math.sqrt;
- local atan2 = math.atan2;
- local AXIS = v3(1, 0, 0);
- local ORIGIN = v3(0, 0, 0);
- -- math functions
- local function rayPlane(p, v, s, n)
- local r = p - s;
- local t = -dot(r, n) / dot(v, n);
- return p + t * v, t;
- end;
- -- support functions
- local function point(direction, p)
- return p;
- end;
- local function pointCloud(direction, cloud)
- local max, maxProj = nil, -huge;
- for i = 1, #cloud do
- local proj = dot(cloud[i], direction)
- if (proj > maxProj) then
- max = cloud[i];
- maxProj = proj;
- end;
- end;
- return max;
- end;
- local function cylinder(direction, cf, size)
- direction = cf:vectorToObjectSpace(direction);
- local radius = min(size.y, size.z);
- local dotT, cPoint = dot(direction, AXIS), v3(size.x, 0, 0);
- local h, t, final;
- if (dotT == 0) then
- final = direction.unit * radius;
- else
- cPoint = dotT > 0 and cPoint or -cPoint;
- h, t = rayPlane(ORIGIN, direction, cPoint, AXIS);
- local diff = h - cPoint;
- if (diff.magnitude > radius) then
- diff = diff.unit * radius;
- end;
- final = cPoint + diff;
- end;
- return cf:pointToWorldSpace(final);
- end;
- local function ellipsoid(direction, cf, size)
- direction = cf:vectorToObjectSpace(direction)
- local p0 = (size * direction).unit;
- return cf:pointToWorldSpace(size*p0);
- end
- return {
- pointCloud = pointCloud;
- cylinder = cylinder;
- ellipsoid = ellipsoid;
- point = point;
- };
- end))
- ModuleScript5.Name = "draw"
- ModuleScript5.Parent = ModuleScript2
- table.insert(cors,sandbox(ModuleScript5,function()
- -- 3D drawing functions
- -- contains a few basic 3D shapes that are useful when testing, etc
- -- EgoMoose
- local wedge = Instance.new("WedgePart");
- wedge.Anchored = true;
- wedge.TopSurface = Enum.SurfaceType.Smooth;
- wedge.BottomSurface = Enum.SurfaceType.Smooth;
- local part = Instance.new("Part");
- part.Size = Vector3.new(0.1, 0.1, 0.1);
- part.Anchored = true;
- part.TopSurface = Enum.SurfaceType.Smooth;
- part.BottomSurface = Enum.SurfaceType.Smooth;
- part.Material = Enum.Material.Neon;
- local function drawPoint(p, parent)
- local point = part:Clone();
- point.CFrame = CFrame.new(p);
- point.BrickColor = BrickColor.Blue();
- point.Parent = parent;
- return point;
- end;
- local function drawLine(a, b, parent)
- local v = (b - a);
- local cf = CFrame.new(a + v * 0.5, b);
- local line = part:Clone();
- line.CFrame = cf;
- line.Size = Vector3.new(0.1, 0.1, v.magnitude);
- line.BrickColor = BrickColor.Red();
- line.Parent = parent;
- return line;
- end
- local function drawTriangle(a, b, c, parent, transparency)
- local edges = {
- {longest = (c - b), other = (a - b), position = b};
- {longest = (a - c), other = (b - c), position = c};
- {longest = (b - a), other = (c - a), position = a};
- };
- table.sort(edges, function(a, b) return a.longest.magnitude > b.longest.magnitude end);
- local edge = edges[1];
- local theta = math.acos(edge.longest.unit:Dot(edge.other.unit));
- local s1 = Vector2.new(edge.other.magnitude * math.cos(theta), edge.other.magnitude * math.sin(theta));
- local s2 = Vector2.new(edge.longest.magnitude - s1.x, s1.y);
- local p1 = edge.position + edge.other * 0.5;
- local p2 = edge.position + edge.longest + (edge.other - edge.longest) * 0.5;
- local right = edge.longest:Cross(edge.other).unit;
- local up = right:Cross(edge.longest).unit;
- local back = edge.longest.unit;
- local cf1 = CFrame.new(
- p1.x, p1.y, p1.z,
- -right.x, up.x, back.x,
- -right.y, up.y, back.y,
- -right.z, up.z, back.z
- );
- local cf2 = CFrame.new(
- p2.x, p2.y, p2.z,
- right.x, up.x, -back.x,
- right.y, up.y, -back.y,
- right.z, up.z, -back.z
- );
- local w1 = wedge:Clone();
- local w2 = wedge:Clone();
- w1.Size = Vector3.new(0.2, s1.y, s1.x);
- w2.Size = Vector3.new(0.2, s2.y, s2.x);
- w1.Transparency = transparency or 0;
- w2.Transparency = transparency or 0;
- w1.CFrame = cf1;
- w2.CFrame = cf2;
- w1.Parent = parent;
- w2.Parent = parent;
- end;
- return {
- triangle = drawTriangle;
- point = drawPoint;
- line = drawLine;
- };
- end))
- ModuleScript6.Name = "vertices"
- ModuleScript6.Parent = ModuleScript2
- table.insert(cors,sandbox(ModuleScript6,function()
- -- calculate corners and points on shape
- -- useful for a lot of 3D math, eg convex hull, GJK, etc.
- -- EgoMoose
- local cos = math.cos;
- local sin = math.sin;
- local insert = table.insert;
- local cornerMultipliers = {
- Vector3.new(1, 1, 1);
- Vector3.new(1, 1, -1);
- Vector3.new(1, -1, -1);
- Vector3.new(-1, -1, -1);
- Vector3.new(-1, -1, 1);
- Vector3.new(-1, 1, 1);
- Vector3.new(-1, 1, -1);
- Vector3.new(1, -1, 1);
- }
- -- the functions that get the vertices
- local function block(cf, size, t)
- for i = 1, #cornerMultipliers do
- insert(t, cf * (size * cornerMultipliers[i]));
- end
- return t;
- end;
- local WEDGE = {1, 3, 4, 5, 6, 8};
- local function wedge(cf, size, t)
- for i = 1, #WEDGE do
- insert(t, cf * (size * cornerMultipliers[WEDGE[i]]));
- end;
- return t;
- end;
- local CORNERWEDGE = {2, 3, 4, 5, 8};
- local function cornerWedge(cf, size, t)
- for i = 1, #CORNERWEDGE do
- insert(t, cf * (size * cornerMultipliers[CORNERWEDGE[i]]));
- end;
- return t;
- end;
- local PI2 = math.pi * 2;
- local function cylinder(cf, size, t, amt)
- local amt = amt or 10;
- local div = PI2 / amt;
- local c1, c2 = cf * (size * Vector3.new(1, 0, 0)), cf * (size * Vector3.new(-1, 0, 0));
- local up, axis = cf * (size * Vector3.new(1, 1, 0)) - c1, (c1 - cf.p).unit;
- for i = 1, amt do
- local theta = div * i;
- -- vector axis angle rotation
- local v = up * cos(theta) + up:Dot(axis) * axis * (1 - cos(theta)) + axis:Cross(up) * sin(theta);
- insert(t, c1 + v);
- insert(t, c2 + v);
- end;
- return t;
- end;
- local function ball(cf, size, t, amt1, amt2)
- local right, forward, up = cf.rightVector * size.x, cf.lookVector * size.z, cf.upVector * size.y;
- local amt1, amt2 = amt1 or 8, amt2 or 8;
- local div1, div2 = PI2 / amt1, PI2 / amt2;
- for i = 1, amt1 do
- local theta = i * div1;
- local horizontal = forward * cos(theta) + right * sin(theta);
- for j = 1, amt2 do
- local theta2 = j * div2;
- local p = cf.p + horizontal * cos(theta2) + up * sin(theta2);
- insert(t, p)
- end;
- end;
- return t;
- end;
- -- special functions
- local function getAllVertices(parts, t)
- local t = t or {};
- for i = 1, #parts do
- local part = parts[i];
- if (part.ClassName == "Part") then
- if (part.Shape == Enum.PartType.Block) then
- block(part.CFrame, part.Size*0.5, t);
- elseif (part.Shape == Enum.PartType.Cylinder) then
- cylinder(part.CFrame, part.Size*0.5, t);
- elseif (part.Shape == Enum.PartType.Ball) then
- ball(part.CFrame, part.Size*0.5, t);
- end;
- elseif (part.ClassName == "WedgePart") then
- wedge(part.CFrame, part.Size*0.5, t);
- elseif (part.ClassName == "CornerWedgePart") then
- cornerWedge(part.CFrame, part.Size*0.5, t);
- elseif (part:IsA("BasePart")) then -- mesh, CSG, truss, etc... just use block
- block(part.CFrame, part.Size*0.5, t);
- end;
- end;
- return t;
- end;
- -- module
- return {
- block = block;
- wedge = wedge;
- cornerWedge = cornerWedge;
- cylinder = cylinder;
- ball = ball;
- getAllVertices = getAllVertices;
- };
- end))
- for i,v in pairs(mas:GetChildren()) do
- v.Parent = game:GetService("Lighting")
- pcall(function() v:MakeJoints() end)
- end
- mas:Destroy()
- for i,v in pairs(cors) do
- spawn(function()
- pcall(v)
- end)
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement