Making A Mesh Deformation Ocean

Prety well written for a first tutorial… Thanks for this! I have been trying to figure out how to import such meshes into Roblox to no avail, and the formula is pretty decent if you ask me. I am playing with some tweaks to make it look a tad smoother but overall, I am so happy to have found your post!
Thanks!

1 Like

Enabling use_normals causes horrible results for me (I’m trying to subdivide a cylinder):

Any idea what might be going on?

EDIT: Was able to fix it. Code I used below:

objects = bpy.context.view_layer.objects
obj = objects.active
def AddBonesAtVertices(obj, length, use_normals):
    if not obj or obj.type != 'MESH':
        return
    points = []
    normals = []
    data = []
    for v in obj.data.vertices:
        p = obj.matrix_world @ v.co
        dir = p * Vector((1, 0, 1))
        dir.normalize()
        n = p + dir * length
        points.append(p)
        if not use_normals:
            n = Vector((p[0], p[1], p[2] + length))
        normals.append(n)
        data.append([p, n])
    bpy.ops.object.mode_set(mode='OBJECT')
    amt = bpy.data.armatures.new(obj.name + "_vBones")
    rig = bpy.data.objects.new(obj.name + '_vRig', amt)
    bpy.context.collection.objects.link(rig)
    objects.active = rig
    names = [] #Will keep bone names
    bpy.ops.object.editmode_toggle()
    for i, l in enumerate(zip(points, normals)):
        bone = amt.edit_bones.new(str(i))
        bone.head = l[0]
        bone.tail = l[1]
        names.append(bone.name) #Add name
    bpy.ops.object.editmode_toggle()
    for v_index, name in enumerate(names):
        #Get the group
        group = obj.vertex_groups.new(name=name)
        #Link the vertex to it
        group.add([v_index], 1, 'REPLACE')
    #Parent and add modifier
    obj.parent = rig
    modifier = obj.modifiers.new(rig.name, "ARMATURE")
    modifier.object = rig

AddBonesAtVertices(obj, 0.5, True)

The result:

3 Likes

Is there a way to prevent the mesh from clipping through objects as an example boats.

1 Like

Is there anyway to make the tile smaller? I set the size to be 500x500, but it stills looks 2000x2000? I needa be able to tile it together, but have gaps for underground areas to work

Sorry for huge bump, but it’s not working as intended :confused:

for _, bone in plane:GetChildren() do
		if not bone:IsA("Bone") then
			continue
		end

		if not self.OriginalPositions[bone] then
			continue
		end

		if Player:DistanceFromCharacter(bone.WorldPosition) > MAX_DISTANCE then
			continue
		end

		local SamplePosition = bone.WorldPosition
		local Wave1 = GerstnerWave(SamplePosition, 150, Vector2.new(1, 0), 0.025, 1, self.SpeedCounter[plane])
		local Wave2 = GerstnerWave(SamplePosition, 175, Vector2.new(0, 0.3), 0.08, 1.25, self.SpeedCounter[plane])
		local Wave3 = GerstnerWave(SamplePosition, 200, Vector2.new(1, 1), 0.04, 1.5, self.SpeedCounter[plane])

		local TotalDisplacement = Wave1 + Wave2 + Wave3

		bone.Position = self.OriginalPositions[bone] + TotalDisplacement
	end

	local BoxSamplePosition = Character:GetPivot().Position - Vector3.new(0, Character.Humanoid.HipHeight / 2, 0)
	local Wave1 = GerstnerWave(BoxSamplePosition, 150, Vector2.new(1, 0), 0.025, 1, self.SpeedCounter[plane])
	local Wave2 = GerstnerWave(BoxSamplePosition, 175, Vector2.new(0, 0.3), 0.08, 1.25, self.SpeedCounter[plane])
	local Wave3 = GerstnerWave(BoxSamplePosition, 200, Vector2.new(1, 1), 0.04, 1.5, self.SpeedCounter[plane])

	local TotalDisplacement = Wave1 + Wave2 + Wave3

	workspace.EEERRR.Position =
		Vector3.new(BoxSamplePosition.X, 13 + TotalDisplacement.Y - workspace.EEERRR.Size.Y / 2, BoxSamplePosition.Z)

ezgif.com-gif-maker - 2022-12-14T122135.697

3 Likes

Sorry for bump, but can you give more detail on how to do this? (Sorry I am new to blender)

The script gives error when ran (note: I am using blender 2.79 because new version isn’t supported on my pc)

The wave position is actually that of the neighboring bones interpolated, Not the position it self

for my game i need the bones specifically sorted in order (i.e. bone 0 and 1 must be right next to each other, not on opposite sides of the plane) bone 0, 1, 2, 3, 4, etc; otherwise i cant optimize it how i want

is there a pre-existing fbx file which has this (5,6,or 7 subdivides), or is there a modified version of the code which does exactly this? it’s very important that the bones are in order.

help is appreciated, thanks

May I ask what kind of optimization you’re trying to do?
You could use the distance from the player for filtering which bones need to update (more frequently).

its not just optimization, my entire system idea revolves around the bones being assorted.
ive already tried your idea, it doesn’t work in my scenario. i need to get the nearest few bones which usually requires sorting or some degree of sorting (which im trying to avoid- i have a lot of bones), and i cant get the nearest few bones how i want and make my system as i made it if their names arent pre-assorted like i described. i have a very specific case.
the details don’t matter, ive considered many other ways of doing this and ive realized the cons of said ways. all i need at this point is a plane with assorted bone, or the code to make such plane. thanks again for your help.

I’m not sure how having the bones a different name at runtime might help with optimization?
But anyway, depending on how you want the sort, you could maybe write a command that would rename the bones how you want them to be in-studio.
When hearing ‘get closest positions’ I thought about octrees. Maybe that’s worth a try too.

octrees are very excessive for what i’m trying to do, especially since i have a solution in mind and all i need is each bones name in numerical order.
and renaming the bones programmatically causes them to move positions. i’ve already tried that yesterday.


done using this oneliner

for k, v in ipairs(workspace.WaterSkin.Plane2:GetChildren()) do if (v.ClassName=='Bone') then v.Name = k end end

genuinely all i need is each bone sorted in order so i can implement my optimized solution. bones 0, 1, 2, and 3 are corners on the plane, what i need is them in order, as well as every other bone in order.

1 Like

You can try checking the bones WorldPosition before it is renamed, and moving it back to where it originally was after the rename.

Not sure if that’ll mess up the mesh though.

1 Like

good solution but it didn’t work. it did the same exact thing shown in my last messages image.

1 Like

you can use a command bar code that loops which renames bones in regions or specific positions starting from top left and moving down towards bottom right.

I have an idea of what kind of optimization you’re trying to do. I’d suggest naming the bones with a coordinate system X,Y.

get the distance between bones and use that distance (10 studs between the bones for instance)

Say there are 70 bones per row and 70 columns, do:
(and this is just a very shallow example)

for x = 1,70 do 
    for y = 1,70 do 
         -- get the bone that is in the position of vector3.new(x*spacebetweenbones,0,y*spacebetweenbones) and name it x.."_"..y
    end
end

ill try this but the issue is that i cannot rename bones, as it causes them to move. and no, thats not the optimization i’m trying to do. i made a system theoretically more optimized. do you have a modified version of the python code that names each bone in order, or do you have a plane with each bone named in order?

nope
you can ask chatgpt to edit the py code to fit your needs. just be specific with it

i solved the issue

local vecOffset = Vector3.new(150, 0, 150)
	local index = 1
	for x = 1, 22 do
		for z = 1, 22 do
			for k, v in ipairs(bones) do
				if ((v.Position - vecOffset).Magnitude <= 2) then
					newBoneOriginalIndices[index] = k
					newBones[index] = v
					index += 1
				end
			end
			vecOffset -= Vector3.new(0, 0, 14.286)
		end
		vecOffset = Vector3.new(vecOffset.X - 14.286, 0, 150)
	end
1 Like

14.286 is the spacing between each bone. 22x22 is how many bone there are on the x and z. this allows me to index bones based on only a simple addition or subtraction to the nearest bones index

twiceLanguish was extremely close, but my friend at school beat him so good game

pretty much what I was trying to recommend but I didn’t know exactly what you wanted to achieve, so I got close enough to let you carry on to success