Solar Panels in BGE/UPBGE

Hello, Blender Geniuses!

You all are a treasure and I mean that… I have a question that may be easy to answer using logic bricks or even a simple bit of python. Is it possible for an object to sense light levels and output a value based on that illumination level? In example, if you have a cube and an animated lamp going from dim to bright, is it possible for the cube to sense the light levels and associate a value with it?

Thank you!

You can fake it.

  1. Detect if an object is in contact with the light’s cone/sphere.
  2. Scale whichever value according to distance, energy, etc.

So in a sense yes, one could make an elaborate guess to emulate that behaviour. Directly detecting brightness of a given surface is trickier. I’m not saying impossible, but I wouldn’t bother.

Judging from the title, I suppose you want to have panels that output bigger numbers when the sun shines brighter on them? I’m a little fried right now but I can give that a spin later, it sounds interesting.

The one concern in my mind is shadows. Calculating the size and weight of an obstruction is fine, a few dozen for real-time and in python of all things, not so much. Just to clarify the code isn’t all that complex but the performance might not be so good so I’d have to test.

Unfortunately there is not an easy solution. If a binary “yes/no” is good enough, you could consider making a physics shape that approximates the lit area and detecting collisions with that.

If this is just for a simple game-mechanic, don’t overthink it. If it’s a simulation of something, you may have to go a lot further.

So what is the game mechanic you are trying to implement?

Beyond that you will need python - and even then, it will be an approximation. You can get the lights intensity and then measure the distance to calculate the attenuation, and from that make a guess at the solar panels energy output. A more advanced solution may a raycast to estimate shadowing. An even more advanced one could use multiple rays distributed across the object, possibly using monte-carlo sampling to get a more accurate estimation over time. It all depends on how accurate the simulation of a solar panel needs to be.

Once upon a time I did a rather unplayable game that computed the light falling on a surface to estimate the pressure of solar wind on an awkward-shaped object. It wasn’t easy, but here it is. It did it “backwards” - using a camera in the position of the light, and for that render-pass, setting all the materials to black except the object of interest. This only worked for a single object, but it was fine for the game.

Gotcha. Yeah it’s not supposed to be incredibly detailed. What I have (in essence) is a cube that has a plane parented to it (with a solar panel texture on it), and what I would like is to be able to be able to differentiate between no light, low light and bright light. Initially I was using logic bricks - I had three empties parented to the solar panel that has Ray sensors with a very high distance output that would collide with a lamp, and dependent on where the lamp was in conjunction to the three empties, it would send a message to the cube with either light_none, light_low or light_high signals. But that’s assuming that the rays collide with it at all… so that’s what I’m wondering… if it can be made simpler and more effective :slight_smile:

A binary yes/no would be okay, but would be really helpful is a none/low/high (3 outputs) to keep it simple. As I mentioned to Liebranca, I used empties with Ray sensors initially, and then tried to use Radar sensor, but the axial vectors (directions you can point the radar) are a little limiting. Plus I need the logic to be exclusive to that particular object only – Basically if I have another object handling the logic and it sends messages, I don’t want it sending a global message that could effect other solar panel objects in the game (if that makes sense). Thank you! :slight_smile:

Rather than checking distance to lamps, would it be possible to somehow get the brightness/color of a certain face and use that? Like before it draws to screen or something idk

You might be able to use the rayCastTo() function in Python, and basically cast a ray from the solar panel to the Sun, and check if it actually hits an object with a “sun” property or not.

If it does, then you can get the distance between the sun and the solar panel, and use that for “brightness”

This poses an interesting concept. Rather than measure the distance of the light, you would just measure how bright the face (solar panel) is. I have no idea how one would do this, however.

I would break up the panel into pieces, or add empties above it representing pieces. Cast a ray from the lamp to every piece, if ray makes contact then that piece is in sunlight so it counts up to the power output.

Now you simply need to get the lamp power value, and do some small math/scaling. So for example 4 piece panel, 2 of them make contact so you got 50% power at full daylight, now simply calculate that 50% power with the value, value = 1 then full 50% power, value = 0.5 then you get 25% power.

I would not use this method in realtime tho. because the calculations would eat up to much resources. But if you have a building game where you place the panels just once then this would be a low performance option. The lamp energy calculation can be done realtime like every 5 seconds or so to save up some resources. But i would not do this to check if it’s in shadow or not (with a handfull panels it would be like 20 calculation/raycasts per set time/tickrate, so imagine if you have like 20+ panels * 4 pieces, it adds up quickly)

Other way as they suggested, simply hit the lamp turn on shadow box, create a cube that fits it, parent it to the lamp, and use that to grab all panels that getting a collision with it, and write a script with python to figure out what piece belongs to what panel and set the power according to that. This would be a cheaper method, but can be less accurate.

1 Like

Alright so, are we talking directional or point lamps? i.e. is the collider a cone or a sphere?

Here I’m basically doing ndotl between UP [0, 0, 1] and DIRN(direction of panel to lamp). The result of that dot product gives you an approximate of how “in light” the top face of the cube is. I then check that value against two thresholds to determine where it lands.

The code is fairly simple:

from mathutils  import Vector;
from bge.render import drawLine;
from bge.logic  import getCurrentController, getCurrentScene;
own=getCurrentController().owner; scene=getCurrentScene();

UP=Vector([0,0,1]); high_tresh=0.5; low_tresh=1.0e-2;

color=[1,0,0]; own["lightLevel"]="no_light";
if lightLevel > low_tresh:    
    if lightLevel > high_tresh:
        color[0:2]=[0,1]; own["lightLevel"]="bright_light";
        color[0:2]=[0, 0.5]; own["lightLevel"]="low_light";

drawLine(own.worldPosition, lamp.worldPosition, color);

And that looks like this:


So now what would remain would be:

  1. Checking if the cube is within the lamps collider
  2. Take lamp to panel distance into consideration if 1 is true

Then checking for obstacles is a tad trickier because I’d have to determine how “in view” of the light the cube is. I have some code to deal with this kind of problem but it’s all in C; I’d have to either wrap a dll or translate it to python, both things would take a while.

Else it’s just a straight raycast and calling it a day. c:

1 Like

This is fantastic. Very well explained. Thank you for this insight. I will do my best to implement a version of this and see if I get it to work. Thank you for your help!