Skip to content

Commit f2a1d73

Browse files
authored
Update CameraControl.java
1 parent 389d91a commit f2a1d73

File tree

1 file changed

+60
-47
lines changed

1 file changed

+60
-47
lines changed

jme3-core/src/main/java/com/jme3/scene/control/CameraControl.java

Lines changed: 60 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009-2021 jMonkeyEngine
2+
* Copyright (c) 2009-2025 jMonkeyEngine
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -44,15 +44,21 @@
4444
import java.io.IOException;
4545

4646
/**
47-
* This Control maintains a reference to a Camera,
48-
* which will be synched with the position (worldTranslation)
49-
* of the current spatial.
47+
* `CameraControl` synchronizes the world transformation (position and rotation)
48+
* of a `Camera` with its attached `Spatial`.
49+
* This control allows a camera to follow a spatial, or a spatial to follow a camera,
50+
* depending on the chosen {@link ControlDirection}.
51+
* <p>
52+
* This is particularly useful for attaching cameras to player characters,
53+
* vehicles, or dynamically controlled objects, ensuring the camera's view
54+
* or the spatial's position/orientation remains synchronized.
55+
* </p>
56+
*
5057
* @author tim
5158
*/
5259
public class CameraControl extends AbstractControl {
5360

54-
public static enum ControlDirection {
55-
61+
public enum ControlDirection {
5662
/**
5763
* Means, that the Camera's transform is "copied"
5864
* to the Transform of the Spatial.
@@ -64,25 +70,31 @@ public static enum ControlDirection {
6470
*/
6571
SpatialToCamera;
6672
}
73+
6774
private Camera camera;
6875
private ControlDirection controlDir = ControlDirection.SpatialToCamera;
6976

7077
/**
71-
* Constructor used for Serialization.
78+
* For serialization only. Do not use.
7279
*/
7380
public CameraControl() {
7481
}
7582

7683
/**
77-
* @param camera The Camera to be synced.
84+
* Creates a new `CameraControl` that synchronizes the spatial's transform to the camera.
85+
* The camera will follow the spatial.
86+
*
87+
* @param camera The Camera to be synced. Cannot be null.
7888
*/
7989
public CameraControl(Camera camera) {
8090
this.camera = camera;
8191
}
8292

8393
/**
84-
* @param camera The Camera to be synced.
85-
* @param controlDir SpatialToCamera or CameraToSpatial
94+
* Creates a new `CameraControl` with a specified synchronization direction.
95+
*
96+
* @param camera The Camera to be synced. Cannot be null.
97+
* @param controlDir The direction of synchronization (SpatialToCamera or CameraToSpatial).
8698
*/
8799
public CameraControl(Camera camera, ControlDirection controlDir) {
88100
this.camera = camera;
@@ -105,61 +117,62 @@ public void setControlDir(ControlDirection controlDir) {
105117
this.controlDir = controlDir;
106118
}
107119

108-
// fields used, when inverting ControlDirection:
109120
@Override
110121
protected void controlUpdate(float tpf) {
111-
if (spatial != null && camera != null) {
112-
switch (controlDir) {
113-
case SpatialToCamera:
114-
camera.setLocation(spatial.getWorldTranslation());
115-
camera.setRotation(spatial.getWorldRotation());
116-
break;
117-
case CameraToSpatial:
118-
// Set the local transform so that the world transform would be equal to the camera's transform.
119-
// Location:
120-
TempVars vars = TempVars.get();
121-
122-
Vector3f vecDiff = vars.vect1.set(camera.getLocation()).subtractLocal(spatial.getWorldTranslation());
123-
spatial.setLocalTranslation(vecDiff.addLocal(spatial.getLocalTranslation()));
124-
125-
// Rotation:
126-
Quaternion worldDiff = vars.quat1.set(camera.getRotation()).subtractLocal(spatial.getWorldRotation());
127-
spatial.setLocalRotation(worldDiff.addLocal(spatial.getLocalRotation()));
128-
vars.release();
129-
break;
130-
}
122+
switch (controlDir) {
123+
case SpatialToCamera:
124+
spatialToCamera();
125+
break;
126+
case CameraToSpatial:
127+
cameraToSpatial();
128+
break;
131129
}
132130
}
133131

132+
/**
133+
* Updates the camera's position and rotation to match the spatial's
134+
* world transformation. The camera will follow the spatial.
135+
*/
136+
private void spatialToCamera() {
137+
camera.setLocation(spatial.getWorldTranslation());
138+
camera.setRotation(spatial.getWorldRotation());
139+
}
140+
141+
/**
142+
* Updates the spatial's local transformation (position and rotation)
143+
* such that its world transformation matches the camera's world transformation.
144+
* The spatial will follow the camera.
145+
*/
146+
private void cameraToSpatial() {
147+
TempVars vars = TempVars.get();
148+
149+
Vector3f position = vars.vect1.set(camera.getLocation()).subtractLocal(spatial.getWorldTranslation());
150+
spatial.setLocalTranslation(position.addLocal(spatial.getLocalTranslation()));
151+
152+
Quaternion rotation = vars.quat1.set(camera.getRotation()).subtractLocal(spatial.getWorldRotation());
153+
spatial.setLocalRotation(rotation.addLocal(spatial.getLocalRotation()));
154+
155+
vars.release();
156+
}
157+
134158
@Override
135159
protected void controlRender(RenderManager rm, ViewPort vp) {
136160
// nothing to do
137161
}
138162

139-
// default implementation from AbstractControl is equivalent
140-
//@Override
141-
//public Control cloneForSpatial(Spatial newSpatial) {
142-
// CameraControl control = new CameraControl(camera, controlDir);
143-
// control.setSpatial(newSpatial);
144-
// control.setEnabled(isEnabled());
145-
// return control;
146-
//}
147-
private static final String CONTROL_DIR_NAME = "controlDir";
148-
private static final String CAMERA_NAME = "camera";
149-
150163
@Override
151164
public void read(JmeImporter im) throws IOException {
152165
super.read(im);
153166
InputCapsule ic = im.getCapsule(this);
154-
controlDir = ic.readEnum(CONTROL_DIR_NAME, ControlDirection.class, ControlDirection.SpatialToCamera);
155-
camera = (Camera)ic.readSavable(CAMERA_NAME, null);
167+
controlDir = ic.readEnum("controlDir", ControlDirection.class, ControlDirection.SpatialToCamera);
168+
camera = (Camera) ic.readSavable("camera", null);
156169
}
157170

158171
@Override
159172
public void write(JmeExporter ex) throws IOException {
160173
super.write(ex);
161174
OutputCapsule oc = ex.getCapsule(this);
162-
oc.write(controlDir, CONTROL_DIR_NAME, ControlDirection.SpatialToCamera);
163-
oc.write(camera, CAMERA_NAME, null);
175+
oc.write(controlDir, "controlDir", ControlDirection.SpatialToCamera);
176+
oc.write(camera, "camera", null);
164177
}
165-
}
178+
}

0 commit comments

Comments
 (0)