+1 vote

I need help with figuring out how to get a mesh to scale non-uniformly.

I'm trying to implement an beam-based weapon in a 3D game. It'll act like Zarya's particle cannon from Overwatch. Specifically, a beam will extend from the player's weapon towards whatever the player is pointing at. While I can use something like a `MeshInstance` to extend to a far distance, I would like the beam to extend to some point until it hits a collision. What would be a good approach to implementing this?

I have looked into using a `Raycast` in order to detect the collisions, yet I still need to shorten the mesh. I'm fine with scaling it. However, scaling operations seem to be uniform; scaling the mesh on the Z-axis scales it from the origin. I need the mesh to be scaled in the direction of where the beam weapon is being pointed.

in Engine

## 2 Answers

0 votes
Best answer

If it is scaled uniformly, it is because the origin is in the center, I don't know how the center is modified in a mesh in godot, but what you can do is create a Position3D or some other node that serves as the parent of the mesh. And then move the mesh so that one of its ends is in position 0.0 of Position3D. To make it work, you have to scale the Position3D, not the mesh, in the opposite direction of the end where the Position3D is. To detect the collision you can put an area with a collision as brother of the mesh and move one of its ends (The same as we did with the mesh). Scaling the Position3D will scale all your children in the same proportion. I don't test if the collision works, I just tried the scaling but I think there shouldn't be any problems.

by (2,252 points)
selected by

The `Position3D` needs to be scaled to the end of the `Position3D`? I don't understand what you're saying.

Sorry my english, I use google to translate, ends = one extreme, one side. Try this test: Add Position3D node, add a MeshInstance node as a child, add a cylinder mesh to the MeshInstance mesh property, go to Transform property and put 1 on the y axis of translation. go to position3d and scale on the y axis

Another way is using shaders, add a meshInstance, add a MeshInstance with a CilinderMesh. And add a ShaderMaterial to the material with this code:
shadertype spatial;
uniform float dist = 10;
void vertex () {
if (VERTEX.y> 0.1) {VERTEX.y = dist; }
}
That scales the mesh according to the value of the dist variable (The scale is in local coordinates), you can access that variable from gdscript, using set
shaderparam (), eg:
material.set
shader_param ("dist", 15.0).
https://docs.godotengine.org/en/3.0/tutorials/3d/vertex_displacement_with_shaders.html

Ah, so use the shader code:

``````uniform float distance = 10;
void vertex() {
if (VERTEX.y > 0.1) {
VERTEX.y = distance;
}
}
``````

Then reference it in GDscript with the code:

``````laser_beam.get_surface_material( 0 ).set_shader_param( "distance", some_length )
``````

I got it.

0 votes

If your going with the scaling plan then try changing the anchor point for the node from center to left or right. Maybe using a control node?

by (617 points)

Didn't know nodes had anchor points. Or are those just unique to `Control`s? If that's the case, then it's not a viable solution; `Control` nodes aren't really useful in 3D.

Didn't know you were in 3d. So try a CSG shape.