+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 by (2,236 points)

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,060 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 (526 points)

Didn't know nodes had anchor points. Or are those just unique to Controls? 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.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.