Skip to content
Open
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
36 changes: 36 additions & 0 deletions jme3-core/src/main/java/com/jme3/light/DirectionalLight.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,39 @@ public class DirectionalLight extends Light {
* Creates a DirectionalLight
*/
public DirectionalLight() {
super();
}

/**
* Creates a DirectionalLight
* @param global if true, the light affects the entire tree from the root node,
* otherwise it only affects the children of the node in which it is attached.
*/
public DirectionalLight(boolean global) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i didn't make a setter for the global param, to make it defacto immutable.
This makes implementation much easier and performant, since we never need to check if the flag changed.

this();
this.global = global;
}

/**
* Creates a DirectionalLight with the given direction
* @param direction the light's direction
*/
public DirectionalLight(Vector3f direction) {
super();
setDirection(direction);
}

/**
* Creates a DirectionalLight with the given direction
* @param direction the light's direction
* @param global if true, the light affects the entire tree from the root node,
* otherwise it only affects the children of the node in which it is attached.
*/
public DirectionalLight(Vector3f direction, boolean global) {
this(direction);
this.global = global;
}

/**
* Creates a DirectionalLight with the given direction and the given color
* @param direction the light's direction
Expand All @@ -79,6 +102,19 @@ public DirectionalLight(Vector3f direction, ColorRGBA color) {
setDirection(direction);
}

/**
* Creates a DirectionalLight with the given direction and the given color
* @param direction the light's direction
* @param color the light's color
* @param global if true, the light affects the entire tree from the root node,
* otherwise it only affects the children of the node in which it is attached.
*/
public DirectionalLight(Vector3f direction, ColorRGBA color, boolean global) {
this(direction, color);
this.global = global;
}


@Override
public void computeLastDistance(Spatial owner) {
// directional lights are after ambient lights
Expand Down
23 changes: 23 additions & 0 deletions jme3-core/src/main/java/com/jme3/light/Light.java
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,38 @@ public int getId(){
* The light name.
*/
protected String name;
protected boolean global = false;

boolean frustumCheckNeeded = true;
boolean intersectsFrustum = false;

protected Light() {
}


protected Light(boolean global) {
this.global = global;
}

protected Light(ColorRGBA color, boolean global) {
setColor(color);
}

protected Light(ColorRGBA color) {
setColor(color);
}


/**
* Returns true if this light affects the entire tree from the root node,
* otherwise returns false, meaning it only affects the children of the node
* in which it is attached.
* @return true if the light is global, otherwise false.
*/
public boolean isGlobal() {
return global;
}

/**
* Returns the color of the light.
*
Expand Down Expand Up @@ -265,6 +286,7 @@ public void write(JmeExporter ex) throws IOException {
oc.write(color, "color", null);
oc.write(enabled, "enabled", true);
oc.write(name, "name", null);
oc.write(global, "global", false);
}

@Override
Expand All @@ -273,6 +295,7 @@ public void read(JmeImporter im) throws IOException {
color = (ColorRGBA) ic.readSavable("color", null);
enabled = ic.readBoolean("enabled", true);
name = ic.readString("name", null);
global = ic.readBoolean("global", false);
}

/**
Expand Down
50 changes: 40 additions & 10 deletions jme3-core/src/main/java/com/jme3/light/LightList.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import com.jme3.util.SortUtil;
import java.io.IOException;
import java.util.*;
import java.util.function.Predicate;

/**
* <code>LightList</code> is used internally by {@link Spatial}s to manage
Expand Down Expand Up @@ -230,37 +231,53 @@ public void sort(boolean transformChanged) {
* @param parent the parent's world-space LightList
*/
public void update(LightList local, LightList parent) {
update(local, parent, null);
}


/**
* Updates a "world-space" light list, using the spatial's local-space
* light list, its parent's world-space light list and an optional filter.
*
* @param local the local-space LightList (not null)
* @param parent the parent's world-space LightList
* @param filter an optional filter to apply to the lights
* (null means no filtering)
*/
public void update(LightList local, LightList parent, Predicate<Light> filter) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added a filter here so that we can exclude global lights from being added the children's internal world lights list.

That's because the rootNode propagates down all the global lights, so when a global light is owned by a children and it is propagated to the same children later, we would end up with the children having two references to the same light, one from its internal local light list and one from the rootNode global light list.
To fix that we would need to deduplicate the lights in the list, that is not great for performances, so instead i've decided to use this filter based approach

// clear the list as it will be reconstructed
// using the arguments
clear();

while (list.length <= local.listSize) {
doubleSize();
}

// add the lights from the local list
System.arraycopy(local.list, 0, list, 0, local.listSize);
for (int i = 0; i < local.listSize; i++) {
// list[i] = local.list[i];
distToOwner[i] = Float.NEGATIVE_INFINITY;

int localListSize = 0;// local.listSize;
for(int i=0;i<local.listSize;i++){
Light l = local.list[i];
if (filter != null && !filter.test(l)) continue;
list[localListSize] = l;
distToOwner[localListSize] = Float.NEGATIVE_INFINITY;
localListSize++;
}

// if the spatial has a parent node, add the lights
// from the parent list as well
if (parent != null) {
int sz = local.listSize + parent.listSize;
int sz = localListSize + parent.listSize;
while (list.length <= sz)
doubleSize();

for (int i = 0; i < parent.listSize; i++) {
int p = i + local.listSize;
int p = i + localListSize;
list[p] = parent.list[i];
distToOwner[p] = Float.NEGATIVE_INFINITY;
}

listSize = local.listSize + parent.listSize;
listSize = localListSize + parent.listSize;
} else {
listSize = local.listSize;
listSize = localListSize;
}
}

Expand Down Expand Up @@ -361,4 +378,17 @@ public void read(JmeImporter im) throws IOException {

Arrays.fill(distToOwner, Float.NEGATIVE_INFINITY);
}

@Override
public String toString() {
StringBuilder sb = new StringBuilder("LightList[");
for (int i = 0; i < listSize; i++) {
sb.append(list[i]);
if (i < listSize - 1) {
sb.append(", ");
}
}
sb.append("]");
return sb.toString();
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is unrelated, but helped with the debug, so i've just left it here

}
61 changes: 61 additions & 0 deletions jme3-core/src/main/java/com/jme3/light/PointLight.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,38 @@ public class PointLight extends Light {
* Creates a PointLight
*/
public PointLight() {
super();
}

/**
* Creates a PointLight
* @param global if true, the light affects the entire tree from the root node,
* otherwise it only affects the children of the node in which it is attached.
*/
public PointLight(boolean global) {
this();
this.global = global;
}

/**
* Creates a PointLight at the given position
* @param position the position in world space
*/
public PointLight(Vector3f position) {
super();
setPosition(position);
}

/**
* Creates a PointLight at the given position
* @param position the position in world space
* @param global if true, the light affects the entire tree from the root node,
* otherwise it only affects the children of the node in which it is attached.
*/
public PointLight(Vector3f position, boolean global) {
this(position);
this.global = global;
}

/**
* Creates a PointLight at the given position and with the given color
Expand All @@ -86,6 +109,18 @@ public PointLight(Vector3f position, ColorRGBA color) {
setPosition(position);
}

/**
* Creates a PointLight at the given position and with the given color
* @param position the position in world space
* @param color the light color
* @param global if true, the light affects the entire tree from the root node,
* otherwise it only affects the children of the node in which it is attached.
*/
public PointLight(Vector3f position, ColorRGBA color, boolean global) {
this(position, color);
this.global = global;
}

/**
* Creates a PointLight at the given position, with the given color and the
* given radius
Expand All @@ -97,6 +132,20 @@ public PointLight(Vector3f position, ColorRGBA color, float radius) {
this(position, color);
setRadius(radius);
}

/**
* Creates a PointLight at the given position, with the given color and the
* given radius
* @param position the position in world space
* @param color the light color
* @param radius the light radius
* @param global if true, the light affects the entire tree from the root node,
* otherwise it only affects the children of the node in which it is attached.
*/
public PointLight(Vector3f position, ColorRGBA color, float radius, boolean global) {
this(position, color, radius);
this.global = global;
}

/**
* Creates a PointLight at the given position, with the given radius
Expand All @@ -107,6 +156,18 @@ public PointLight(Vector3f position, float radius) {
this(position);
setRadius(radius);
}

/**
* Creates a PointLight at the given position, with the given radius
* @param position the position in world space
* @param radius the light radius
* @param global if true, the light affects the entire tree from the root node,
* otherwise it only affects the children of the node in which it is attached.
*/
public PointLight(Vector3f position, float radius, boolean global) {
this(position, radius);
this.global = global;
}

@Override
public void computeLastDistance(Spatial owner) {
Expand Down
Loading
Loading