I want to adjust the size of the plane mesh according to the camera view in the 3D scene, that is, how big an area does the camera see in x and z coordinates, how do I calculate this or is there a ready-made function?
How to adjust mesh size with 3D camera field of view?
unicornlox What are you planning to accomplish with this?
xyz When we first open the 3D scene editor, there is a grid-like surface appearance, I will try to get that kind of appearance.
unicornlox What this has to do with scaling a plane?
xyz I thought it could be done with the logic of infinite terrain. What is your opinion about this and how to do such a thing?
- Edited
using Godot;
using NuGet.Configuration;
using System;
public partial class SquareFloor : Node3D
{
Camera3D Cam;
Vector3 PlaneNormal;
//float PlaneDistance;
Godot.Collections.Array<Plane> Vectorfrust;
ImmediateMesh DrawMesh;
MeshInstance3D MeshSet;
Vector3? IntersectionPoint;
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
Cam = GetNode<Camera3D>("Camera3D");
MeshSet = new MeshInstance3D();
AddChild(MeshSet);
DrawMesh = new ImmediateMesh();
//MeshSet.Mesh = DrawMesh;
}
// Called every frame. 'delta' is the elapsed time since the previous frame.
public override void _Process(double delta)
{
if (DrawMesh.GetSurfaceCount() < 250)
{
DrawPlane ();
}
}
private void DrawPlane ()
{
Vectorfrust = Cam.GetFrustum();
//DrawMesh.ClearSurfaces();
DrawMesh.SurfaceBegin(Mesh.PrimitiveType.Lines);
foreach (Plane plane in Vectorfrust)
{
PlaneNormal = plane.Normal;
//PlaneDistance = plane.D;
//IntersectionPoint = plane.IntersectsSegment(Vector3.Zero, PlaneNormal);
IntersectionPointControl(plane, Vector3.Zero, PlaneNormal);
IntersectionPointControl(plane, Vector3.Right, PlaneNormal);
}
DrawMesh.SurfaceSetColor(Color.FromHtml("#d4191e"));
DrawMesh.SurfaceEnd();
MeshSet.Mesh = DrawMesh;
}
private void IntersectionPointControl (Plane plane, Vector3 vec3, Vector3 plnrml)
{
IntersectionPoint = plane.IntersectsSegment(vec3, plnrml);
if (IntersectionPoint != null)
{
DrawMesh.SurfaceAddVertex((Vector3) IntersectionPoint);
}
}
}
why drawings do not appear on the screen where is my fault?
- Edited
unicornlox You still haven't defined/communicated the problem clearly. At this point in conversation, @Megalomaniak often appears, posting a link to this page
xyz If I understood correctly they want to create a construction grid. I'd consider array mesh for it.
for something more brain-dead, try using a big fat plane mesh with a repeating texture, and three additional meshes for the colored axis.
Megalomaniak If I understood correctly they want to create a construction grid. I'd consider array mesh for it.
The original question looks closer to how to fit something into camera frustum. Then out of the blue it mutated into grid construction... that I suspect needs fitting into camera frustum? So who knows, might be anything at this point
I want to get a grid-like plane, that's all, but it should appear whatever the position of the camera, just like in the editor 3D scene.
- Edited
packrat If the grid could be visible regardless of the position of the camera in the 3D scene, this idea would work for me.
Megalomaniak I want to create a grid with lines in the field of view of the camera with ImmediateMesh, how do I do it.arraymesh is more complicated than ImmediateMesh.
xyz I want to get a grid-like plane, that's all, but it should appear whatever the position of the camera, just like in the editor 3D scene.
- Edited
unicornlox Grids like that are not drawn on planes in the world. Instead they are procedurally projected by a fragment shader onto a camera facing quad covering the entire viewport. The approach is described here. It's similar to how the procedural skyboxes are rendered.
- Edited
unicornlox
Here's the shader. It will project "ground grid" to any piece of geometry. It just uses geometry as a silhouette to render pixels. It will write the depth value as well making the grid always appear on ground no matter where the geometry is.
To make the grid always visible, regardless of camera position/orientation, parent a quad or a 3D sprite to the camera so that it faces the camera and covers the whole view, and assign the shader to it.
shader_type spatial;
render_mode blend_mix,depth_draw_opaque, unshaded;
uniform vec4 albedo: source_color;
uniform float fadeDistance = 100.0;
uniform float unitSize = 1.0;
uniform float lineThickness = 1.0;
void fragment() {
// ray from camera to fragemnt in wrold space
vec3 rayWorld = normalize(mat3(INV_VIEW_MATRIX) * VIEW);
// calculate fragment position in world space
vec3 posWorld;
float t = -CAMERA_POSITION_WORLD.y / rayWorld.y;
posWorld.y = 0.0;
posWorld.xz = CAMERA_POSITION_WORLD.xz + t * rayWorld.xz;
// calculate planar distance from camera to fragment (for fading)
float distPlanar = distance(posWorld.xz, CAMERA_POSITION_WORLD.xz);
// calculate line mask, using a bit of fwidth() magic to make line width not affected by perspective
vec2 line = step(fwidth(posWorld.xz) * lineThickness / unitSize, fract(posWorld.xz / unitSize));
float lineMask = 1.0 - clamp(line.x * line.y, 0.0, 1.0);
// eliminate grid above the horizon
lineMask *= step(t, 0.0);
// fade into distance
lineMask *= mix(1.0, 0.0, clamp(distPlanar/fadeDistance, 0.0, 1.0));
// write ground plane depth into z buffer
vec4 pp = (PROJECTION_MATRIX * (VIEW_MATRIX * vec4(posWorld, 1.0)));
DEPTH = pp.z / pp.w;
ALPHA = lineMask * albedo.a;
ALBEDO = albedo.rgb;
}
xyz Thank you very much, I've been looking for this for days.I will try it right away.
xyz my friend thanks a lot this is what will work for me but how do I change the shader variables with gdscript or c#, from within the code of my game? I'm talking about these variables of the shader, how can I change them?
float fadeDistance = 100.0;
uniform float unitSize = 1.0;
xyz ok man I learned how to access the shader code from inside the code.
using Godot;
using System;
public partial class SquareFloor : Node3D
{
Camera3D Cam;
MeshInstance3D MeshPlaneThis;
PlaneMesh MeshPlane;
ShaderMaterial MeshPlaneShaderMat;
//Shader MeshPlaneShader;
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
Cam = GetNode<Camera3D>("Camera3D");
MeshPlaneThis = GetNode<MeshInstance3D>("MeshInstance3D");
MeshPlane = (PlaneMesh) MeshPlaneThis.Mesh;
MeshPlaneShaderMat = (ShaderMaterial) MeshPlane.Material;
//MeshPlaneShader = MeshPlaneShaderMat.Shader;
MeshPlaneShaderMat.SetShaderParameter((StringName)"fadeDistance", 100.0);
MeshPlaneShaderMat.SetShaderParameter((StringName)"unitSize", 1.0);
}
// Called every frame. 'delta' is the elapsed time since the previous frame.
public override void _Process(double delta)
{
}
private void ChangeShaderParam()
{}
}
- Edited
unicornlox Use Material::SetShaderParameter()
EDIT: Ok you already figured it out.