Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions movement/look_at_3d/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Defold Protocol Buffer Text Files (https://github.com/github/linguist/issues/5091)
*.animationset linguist-language=JSON5
*.atlas linguist-language=JSON5
*.camera linguist-language=JSON5
*.collection linguist-language=JSON5
*.collectionfactory linguist-language=JSON5
*.collectionproxy linguist-language=JSON5
*.collisionobject linguist-language=JSON5
*.cubemap linguist-language=JSON5
*.display_profiles linguist-language=JSON5
*.factory linguist-language=JSON5
*.font linguist-language=JSON5
*.gamepads linguist-language=JSON5
*.go linguist-language=JSON5
*.gui linguist-language=JSON5
*.input_binding linguist-language=JSON5
*.label linguist-language=JSON5
*.material linguist-language=JSON5
*.mesh linguist-language=JSON5
*.model linguist-language=JSON5
*.particlefx linguist-language=JSON5
*.render linguist-language=JSON5
*.sound linguist-language=JSON5
*.sprite linguist-language=JSON5
*.spinemodel linguist-language=JSON5
*.spinescene linguist-language=JSON5
*.texture_profiles linguist-language=JSON5
*.tilemap linguist-language=JSON5
*.tilesource linguist-language=JSON5

# Defold JSON Files
*.buffer linguist-language=JSON

# Defold GLSL Shaders
*.fp linguist-language=GLSL
*.vp linguist-language=GLSL

# Defold Lua Files
*.editor_script linguist-language=Lua
*.render_script linguist-language=Lua
*.script linguist-language=Lua
*.gui_script linguist-language=Lua
11 changes: 11 additions & 0 deletions movement/look_at_3d/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/.editor_settings
/.internal
/build
.externalToolBuilders
.DS_Store
Thumbs.db
.lock-wscript
*.pyc
.project
.cproject
builtins
81 changes: 81 additions & 0 deletions movement/look_at_3d/example.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
---
title: Rotate 3D object towards the mouse cursor
brief: Learn how to rotate a 3D object towards the mouse cursor.
author_ids:
- evgenii-starostin
scripts: turret_controller.script, camera_controller.script
thumbnail: thumbnail.webp
tags: movement
---
This example demonstrates how to rotate a 3D object towards the mouse cursor.

## Project Structure
```
- camera.go
- camera
- camera_controller.script
floor.go
- floor
- floor_uv_scale.script
root.go
- turret.go
- turret
- turret_controller.script
- base
```

## How It Works
First, the script that controls the rotation needs a reference to the active camera. This is done by sending a message in `init`:

```lua
msg.post("/turret#turret_controller", "register_camera", {
url = msg.url("#camera")
})
```

In turret_controller.script we use the camera to build a picking ray - a line that starts at the camera and goes through the cursor position in the world:

```lua
-- z = 0 -> near plane, z = 1 -> far plane (normalized depth)
local p0 = camera.screen_to_world(
vmath.vector3(self.mouse_x, self.mouse_y, 0),
self.camera_url
)

local p1 = camera.screen_to_world(
vmath.vector3(self.mouse_x, self.mouse_y, 1),
self.camera_url
)

local ray = p1 - p0
```

Then we intersect this ray with the horizontal plane at the turret's height (y = gun_pos.y):
```lua
go.update_world_transform()
local gun_pos = go.get_world_position()

-- avoid division by zero when the ray is parallel to the plane
if math.abs(ray.y) < 0.00001 then
return
end

local t = (gun_pos.y - p0.y) / ray.y
local target = p0 + ray * t
```

Finally, we compute the yaw angle from the turret to the target and rotate the object around the Y axis. atan2(dx, dz) assumes the model faces +Z at angle 0:
```lua
local dx = target.x - gun_pos.x
local dz = target.z - gun_pos.z

if math.abs(dx) + math.abs(dz) < 0.00001 then
return
end

local angle = math.atan2(dx, dz)

go.set_rotation(
vmath.quat_rotation_y(angle)
)
```
26 changes: 26 additions & 0 deletions movement/look_at_3d/game.project
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[bootstrap]
main_collection = /main/main.collectionc

[script]
shared_state = 1

[display]
width = 720
height = 720
high_dpi = 1

[android]
input_method = HiddenInputField

[physics]
gravity_y = -1000.0
scale = 0.01

[html5]
scale_mode = no_scale

[project]
title = Look at 3D
dependencies =
developer =

4 changes: 4 additions & 0 deletions movement/look_at_3d/input/game.input_binding
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
mouse_trigger {
input: MOUSE_BUTTON_1
action: "touch"
}
5 changes: 5 additions & 0 deletions movement/look_at_3d/main/camera_controller.script
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
function init(self)
msg.post("/turret#turret_controller", "register_camera", {
url = msg.url("#camera")
})
end
3 changes: 3 additions & 0 deletions movement/look_at_3d/main/floor_uv_scale.script
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function init(self)
go.set("#floor", "uv_scale", vmath.vector4(10, 10, 0, 0))
end
Binary file added movement/look_at_3d/main/images/colormap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added movement/look_at_3d/main/images/texture_02.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
107 changes: 107 additions & 0 deletions movement/look_at_3d/main/main.collection
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
name: "main"
scale_along_z: 0
embedded_instances {
id: "root"
children: "turret"
data: "embedded_components {\n"
" id: \"base\"\n"
" type: \"model\"\n"
" data: \"mesh: \\\"/main/models/base.glb\\\"\\n"
"skeleton: \\\"/main/models/base.glb\\\"\\n"
"animations: \\\"/main/models/base.glb\\\"\\n"
"name: \\\"{{NAME}}\\\"\\n"
"materials {\\n"
" name: \\\"default\\\"\\n"
" material: \\\"/main/materials/static/unlit.material\\\"\\n"
" textures {\\n"
" sampler: \\\"tex0\\\"\\n"
" texture: \\\"/main/images/colormap.png\\\"\\n"
" }\\n"
"}\\n"
"\"\n"
"}\n"
""
}
embedded_instances {
id: "camera"
data: "components {\n"
" id: \"camera_controller\"\n"
" component: \"/main/camera_controller.script\"\n"
"}\n"
"embedded_components {\n"
" id: \"camera\"\n"
" type: \"camera\"\n"
" data: \"aspect_ratio: 1.0\\n"
"fov: 1.047\\n"
"near_z: 2.1\\n"
"far_z: 30.0\\n"
"auto_aspect_ratio: 1\\n"
"orthographic_zoom: 116.0\\n"
"\"\n"
"}\n"
""
position {
y: 5.0
z: 6.0
}
rotation {
x: -0.34202015
w: 0.9396926
}
}
embedded_instances {
id: "turret"
data: "components {\n"
" id: \"turret_controller\"\n"
" component: \"/main/turret_controller.script\"\n"
"}\n"
"embedded_components {\n"
" id: \"turret\"\n"
" type: \"model\"\n"
" data: \"mesh: \\\"/main/models/turret.glb\\\"\\n"
"skeleton: \\\"/main/models/turret.glb\\\"\\n"
"animations: \\\"/main/models/turret.glb\\\"\\n"
"name: \\\"{{NAME}}\\\"\\n"
"materials {\\n"
" name: \\\"default\\\"\\n"
" material: \\\"/main/materials/skinned/unlit_skinned.material\\\"\\n"
" textures {\\n"
" sampler: \\\"tex0\\\"\\n"
" texture: \\\"/main/images/colormap.png\\\"\\n"
" }\\n"
"}\\n"
"\"\n"
"}\n"
""
}
embedded_instances {
id: "floor"
data: "components {\n"
" id: \"floor_uv_scale\"\n"
" component: \"/main/floor_uv_scale.script\"\n"
"}\n"
"embedded_components {\n"
" id: \"floor\"\n"
" type: \"model\"\n"
" data: \"mesh: \\\"/builtins/assets/gltf/quad.gltf\\\"\\n"
"name: \\\"{{NAME}}\\\"\\n"
"materials {\\n"
" name: \\\"default\\\"\\n"
" material: \\\"/main/materials/static/unlit.material\\\"\\n"
" textures {\\n"
" sampler: \\\"tex0\\\"\\n"
" texture: \\\"/main/images/texture_02.png\\\"\\n"
" }\\n"
"}\\n"
"\"\n"
"}\n"
""
rotation {
x: -0.70710677
w: 0.70710677
}
scale3 {
x: 100.0
y: 100.0
}
}
16 changes: 16 additions & 0 deletions movement/look_at_3d/main/materials/skinned/unlit_skinned.fp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#version 140

in vec2 var_texcoord0;
uniform mediump sampler2D tex0;
out lowp vec4 final_color;
uniform fs_uniforms
{
mediump vec4 tint;
};

void main()
{
vec4 tint_pm = vec4(tint.xyz * tint.w, tint.w);
vec4 color = texture(tex0, var_texcoord0.xy) * tint_pm;
final_color = color;
}
30 changes: 30 additions & 0 deletions movement/look_at_3d/main/materials/skinned/unlit_skinned.material
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: "unlit"
tags: "model"
vertex_program: "/main/materials/skinned/unlit_skinned.vp"
fragment_program: "/main/materials/skinned/unlit_skinned.fp"
vertex_space: VERTEX_SPACE_LOCAL
vertex_constants {
name: "mtx_worldview"
type: CONSTANT_TYPE_WORLDVIEW
}
vertex_constants {
name: "mtx_proj"
type: CONSTANT_TYPE_PROJECTION
}
fragment_constants {
name: "tint"
type: CONSTANT_TYPE_USER
value {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
}
samplers {
name: "tex0"
wrap_u: WRAP_MODE_CLAMP_TO_EDGE
wrap_v: WRAP_MODE_CLAMP_TO_EDGE
filter_min: FILTER_MODE_MIN_LINEAR
filter_mag: FILTER_MODE_MAG_LINEAR
}
27 changes: 27 additions & 0 deletions movement/look_at_3d/main/materials/skinned/unlit_skinned.vp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#version 140

in highp vec4 position;
in mediump vec2 texcoord0;
in mediump vec4 bone_weights;
in mediump vec4 bone_indices;

out mediump vec2 var_texcoord0;

uniform vs_uniforms
{
mediump mat4 mtx_worldview;
mediump mat4 mtx_proj;
mediump vec4 animation_data;
};

#include "/builtins/materials/skinning.glsl"

void main()
{
vec4 skinned_position = get_skinned_position(position);

var_texcoord0 = texcoord0;

vec4 p = mtx_worldview * vec4(skinned_position.xyz, 1.0);
gl_Position = mtx_proj * p;
}
25 changes: 25 additions & 0 deletions movement/look_at_3d/main/materials/static/unlit.fp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#version 140


in mediump vec2 var_texcoord0;
uniform mediump sampler2D tex0;
in highp mat4 var_view;

out vec4 out_fragColor;

uniform fs_uniforms
{
mediump vec4 tint;
};

void main()
{
// Pre-multiply alpha since all runtime textures already are
vec4 tint_pm = vec4(tint.xyz * tint.w, tint.w);

// Sample the texture at the fragment's texture coordinates.
vec4 color = texture(tex0, var_texcoord0.xy) * tint_pm;

// Output the sampled color.
out_fragColor = color;
}
Loading
Loading