local function resize(part, worldOffset)
local offset = part.CFrame:ToObjectSpace(worldOffset)
part.Size = part.Size + absVector3(offset)
part.CFrame = part.CFrame + offset / 2
end
local function adjust(wall, newLength)
local worldOffset = wall.dir * (newLength - wall.length)
resize(wall.model.Wall1, worldOffset)
resize(wall.model.Wall2, worldOffset)
wall.length = newLength
end
Hmm ok,
local function resize(part, worldOffset)
local offset = part.CFrame:ToObjectSpace(worldOffset) -- error
part.Size = part.Size + absVector3(offset)
part.CFrame = part.CFrame + offset / 2
end
[bad argument #1 to ‘ToObjectSpace’ (CFrame expected, got Vector3)]
which not sure how it’s getting a Vector3 if it’s being called like this
resize(wall.model.Wall1, worldOffset)
as Wall1 is just a part
Should be :VectorToObjectSpace()
instead of :ToObjectSpace()
.
local function getAdditionalLength(angleBetweenWalls)
return math.sin(angleBetweenWalls / 2) * 0.4 / 2 -- LINE 40
end
and it’s being called from here
local length = getAdditionalLength(getAngle(dir, otherWall.dir)) -- LINE 92
It is a really simple fix. Just missing a keyword. You should be able to fix the simple bugs but let me know if there is anything major.
getAngle
didn’t return the value:
local function getAngle(wallDirA, wallDirB)
math.acos(wallDirA:Dot(wallDirB))
end
local function getAngle(wallDirA, wallDirB)
return math.acos(wallDirA:Dot(wallDirB))
end
edit: the heck i swear i clicked reply
Welp, got no errors, but at the same, it doesn’t work the walls are being resized, but it’s just making one wall skinnier, not actually filling the gap
Just testing more, it actually makes 1 wall thicker, and then moves the smaller wall over a bit. So in that pic, the skinnier wall stays at 0.2 for each wall (making it 0.4 thick) but the fatter wall gets given a random thickness (like 0.382 for each wall, making it 0.382*2) in thickness
Ah, I see the issues. Try this:
local abs = math.abs
local function absVector3(v3)
return Vector3.new(
abs(v3.X),
abs(v3.Y),
abs(v3.Z)
)
end
local function resize(part, worldOffset)
local offset = part.CFrame:VectorToObjectSpace(worldOffset)
part.Size = part.Size + absVector3(offset)
part.CFrame = part.CFrame + worldOffset / 2
end
local function adjust(wall, newLength)
-- Need to offset toward the poll, not away from it.
local worldOffset = wall.dir * (wall.length - newLength)
resize(wall.model.Wall1, worldOffset)
resize(wall.model.Wall2, worldOffset)
wall.length = newLength
end
Upon closer examination I’ll bet you’ll find the wall width didn’t decrease, but the wall halves were moved closer together.
I used the opposite dir in my code than what the original code I gave you wanted. I’ve reversed it in two places. In addToPoll()
:
local dir = (poll - otherPoll).Unit
and in adjust()
I changed the worldOffset
back:
local worldOffset = wall.dir * (newLength - wall.length)
Here is code with most of the changes:
local wallModel = game.ReplicatedStorage.Wall
local WALL_HEIGHT = 5
local WALL_OFFSET = Vector3.new(0, WALL_HEIGHT, 0)
local UP = Vector3.new(0, 1, 0)
local function getAdditionalLength(angleBetweenWalls)
return math.sin(angleBetweenWalls / 2) * 0.5 / 2
end
local function getAngle(wallDirA, wallDirB)
return math.acos(wallDirA:Dot(wallDirB))
end
local function snapToGrid(pos)
return Vector3.new(
math.floor(pos.X + 0.5),
math.floor(pos.Y + 0.5),
math.floor(pos.Z + 0.5)
)
end
local abs = math.abs
local function absVector3(v3)
return Vector3.new(
abs(v3.X),
abs(v3.Y),
abs(v3.Z)
)
end
local function resize(part, worldOffset)
local offset = part.CFrame:VectorToObjectSpace(worldOffset)
part.Size = part.Size + absVector3(offset)
part.CFrame = part.CFrame + worldOffset / 2
end
local function adjust(wall, newLength)
local worldOffset = wall.dir * (newLength - wall.length)
resize(wall.model.Wall1, worldOffset)
resize(wall.model.Wall2, worldOffset)
wall.length = newLength
end
local POLL_KEY = '%d %d %d'
local function getWalls(polls, pos)
local key = POLL_KEY:format(pos.X, pos.Y, pos.Z)
local walls = polls[key]
if not walls then
walls = {}
polls[key] = walls
end
return walls
end
local function addToPoll(polls, poll, otherPoll, model)
local walls = getWalls(polls, poll)
local maxLength = 0
local dir = (poll - otherPoll).Unit
local wall = {
length = maxLength;
model = model;
dir = dir;
}
for otherWall in next, walls do
local length = getAdditionalLength(getAngle(dir, otherWall.dir))
if length > maxLength then
maxLength = length
end
if length > otherWall.length then
adjust(otherWall, length)
end
end
adjust(wall, maxLength)
walls[wall] = true
end
local function placeWall(polls)
local mouse = game.Players.LocalPlayer:GetMouse()
mouse.Button1Down:Wait()
local pollA = snapToGrid(mouse.Hit.p)
mouse.Button1Down:Wait()
local pollB = snapToGrid(mouse.Hit.p)
local model = wallModel:Clone()
model:SetPrimaryPartCFrame(CFrame.fromMatrix(
(pollA + pollB) / 2 + WALL_OFFSET,
(pollA - pollB).Unit,
UP
))
addToPoll(polls, pollA, pollB, model)
addToPoll(polls, pollB, pollA, model)
end
Still has the same problem of them being sized too big
Made the change in adjust
local function adjust(wall, newLength)
-- Need to offset toward the poll, not away from it.
local worldOffset = wall.dir * (newLength - wall.length)
resize(wall.model.Wall1, worldOffset)
resize(wall.model.Wall2, worldOffset)
wall.length = newLength
end
and addToPole
local function addToPoll(polls, poll, otherPoll, model)
local walls = getWalls(polls, poll)
local maxLength = 0
local dir = (poll - otherPoll).Unit
local wall = {
length = maxLength;
model = model;
dir = dir;
}
for otherWall in next, walls do
local length = getAdditionalLength(getAngle(dir, otherWall.dir))
if length > maxLength then
maxLength = length
end
if length > otherWall.length then
adjust(otherWall, length)
end
end
adjust(wall, maxLength)
walls[wall] = true
end
Sorry, I had to go do something else. I redid the angle math and got a different result. Here is my diagram:
(Note, the theta should be halved in the image in the equation for x.)
Which means that this function needs to be different:
local WALL_THICKNESS = 1
local function getAdditionalLength(angleBetweenWalls)
return math.tan(angleBetweenWalls / 2) * WALL_THICKNESS / 2
end
Ended up making the walls even longer
I did edit the wall thickness to 0.4 instead of 1, as each wall is 0.2 in thickness (0.2+0.2=0.4)
Or, should wall thickness be set to 0.2? Technically the wall model is 0.4 in thickness, but is that code based on the individual parts thickness?
Holy what… ok, so I tried setting the thickness to 0.2, and got this
It’s so beautiful
Unfortunately, it kinda stops there
90 degree still has the lil gap
So for some reason, certain angles work like magic, other angles just aren’t right
Messing around with more angles
lol
After staring at the code I saw it and hit myself on the head.
This:
local function getAngle(wallDirA, wallDirB)
return math.acos(wallDirA:Dot(wallDirB))
end
Should be this:
local function getAngle(wallDirA, wallDirB)
return wallDirA:Dot(wallDirB)
end
I think that is the last bug!
Also, the thickness should be 0.4 in that code I gave you, but you could also use this:
local WALL_HALF_THICKNESS = 0.2
local function getAdditionalLength(angleBetweenWalls)
return math.tan(angleBetweenWalls / 2) * WALL_HALF_THICKNESS
end
local function getAngle(wallDirA, wallDirB)
return wallDirA:Dot(wallDirB)
end
tried that and it did nothing now the walls don’t resize at all
Also are you sure it should be 0.4? Cause it worked like a charm with 0.2 for some of the angles, but didnt work at all with 0.4
Is there a test place you can show me? I’d like to see the behavior in action. We could also chat in game / group until we have a solution others could use.
local WALL_THICKNESS = 0.4
local function getAdditionalLength(angleBetweenWalls)
return math.tan(angleBetweenWalls / 2) * WALL_THICKNESS / 2
end
local function getAngle(wallDirA, wallDirB)
return math.acos(wallDirA:Dot(wallDirB))
end
This seemed to work with 90 degree walls
But was adding like 2-3 studs on any other angle
I can invite you to a team create?? i think you need to be on my friends list tho
Good news! Last night we got the last script posted here working and we also added a couple more features. It now handles both halves of each wall (inner / outer or in other words left / right) differently so that when coloring them they don’t glitch the graphics where they overlap. In addition, we discovered that when the smallest angle between the walls is less than 90 degrees, the walls can’t be brought together to form a clean point. Doing so makes the wall’s thickness stick out the other end and form an hour glass looking shape around the poll. So, one wall is chosen to form the end and the other wall stops inside of that wall. This code also handles multiple-wall intersections by resizing the left half with the right half of the wall on its left side, and the right half with the left half of the wall on its right side (forward being toward the poll).
If anyone runs across a similar issue at some point, here is the code. Sorry if the math variables are not well named, there so many related in various special ways that it became difficult to find good names for them.
local WALL_HEIGHT = 12
local WALL_OFFSET = Vector3.new(0, WALL_HEIGHT, 0)
local UP = Vector3.new(0, 1, 0)
local WALL_HALF_THICKNESS = 0.2
local abs = math.abs
local function absVector3(v3)
return Vector3.new(
abs(v3.X),
abs(v3.Y),
abs(v3.Z)
)
end
local function setSize(wall, half, length)
local delta = length - wall.length[half]
local dir = wall.dir * delta
local part = wall[half]
local offset = part.CFrame:VectorToObjectSpace(dir)
part.Size = part.Size + math.sign(delta) * absVector3(offset)
part.CFrame = part.CFrame + dir / 2
wall.length[half] = length
end
local function adjust(wall, other)
local angle = math.acos(wall.rightDir:Dot(-other.rightDir))
local wallLength, otherLength
if math.abs(angle - math.pi/2) < 0.001 then
if wall.dir:Dot(other.rightDir - wall.rightDir) > 0 then
wallLength = WALL_HALF_THICKNESS
otherLength = 0
else
wallLength = 0
otherLength = -WALL_HALF_THICKNESS
end
elseif angle > math.pi/2 then
local otherAngle = math.acos(wall.dir:Dot(other.dir))
local sign = -math.sign(wall.rightDir:Dot(other.dir))
wallLength = sign * WALL_HALF_THICKNESS / math.tan(otherAngle)
otherLength = sign * math.sqrt(wallLength^2 + WALL_HALF_THICKNESS^2)
else
wallLength = math.tan(angle / 2) * WALL_HALF_THICKNESS
otherLength = wallLength
end
setSize(wall, 'left', wallLength)
setSize(other, 'right', otherLength)
end
local POLL_KEY = '%d %d %d'
local function getWalls(polls, pos)
local key = POLL_KEY:format(pos.X, pos.Y, pos.Z)
local walls = polls[key]
if not walls then
walls = {}
polls[key] = walls
end
return walls
end
local function addToPoll(polls, poll, otherPoll, model)
local walls = getWalls(polls, poll)
local dir = (poll - otherPoll).Unit
local rightDir = dir:Cross(UP)
local right, left = model.Wall1, model.Wall2
local toRight = right.Position - left.Position
if toRight:Dot(rightDir) < 0 then
right, left = left, right
end
local wall = {
length = {
left = 0;
right = 0;
};
model = model;
right = right;
left = left;
dir = dir;
rightDir = rightDir;
}
if not next(walls) then
walls[wall] = true
return
end
local leftIsFound
local leftDot
local leftWall
local rightIsFound
local rightDot
local rightWall
for otherWall in next, walls do
local dot = dir:Dot(otherWall.dir)
local isRight = rightDir:Dot(otherWall.dir) < 0
if isRight then
if not rightIsFound or not rightDot or dot > rightDot then
rightIsFound = true
rightDot = dot
rightWall = otherWall
end
if not leftIsFound and (not leftDot or dot < leftDot) then
leftDot = dot
leftWall = otherWall
end
else
if not rightIsFound and (not rightDot or dot < rightDot) then
rightDot = dot
rightWall = otherWall
end
if not leftIsFound or not leftDot or dot > leftDot then
leftIsFound = true
leftDot = dot
leftWall = otherWall
end
end
end
adjust(wall, leftWall)
adjust(rightWall, wall)
walls[wall] = true
end
local function placeWall(polls)
local mouse = game.Players.LocalPlayer:GetMouse()
mouse.Button1Down:Wait()
local pollA = snapToGrid(mouse.Hit.p)
mouse.Button1Down:Wait()
local pollB = snapToGrid(mouse.Hit.p)
local model = wallModel:Clone()
model:SetPrimaryPartCFrame(CFrame.fromMatrix(
(pollA + pollB) / 2 + WALL_OFFSET,
(pollA - pollB).Unit,
UP
))
addToPoll(polls, pollA, pollB, model)
addToPoll(polls, pollB, pollA, model)
model.Parent = workspace
end