# Question
Title: In OpenGL, why do people worry that the accuracy of the depth buffer gets worse the farther away?
I'm really new to graphics programming, so I'm learning about depth buffers with this article.

I got that the conversion from View Space to NDC is non-linear, but I think we can avoid the problem by doing the following. I suppose I could make it linear by doing the following, but why don't people do this?

*Main code:*

```
float near = 0.1f, far = 100.0f;
projection = glm::perspective(glm::radians(45.0f), WIDTH/HEIGHT, near, far);
projection[2][2] = 2.0f/(near-far);          // like ortho only about z
projection[3][2] = (near+far)/(near-far);    // like ortho only about z

```

*Vertex shader:*

```
vec4 outvec = projection * view * model * vex4(VertexCoord, 1.0);
outvec.z *= outvec.w;   // I prevent dividing by w
gl_Position = outvec;

```

# Answer
The main reason the conversion from View Space to Normalised Device Coordinates is non-linear is **floating-point precision**, amongst others. Using a multiplicative inverse (thus, non-linear) relation over a linear one is due to a trade-off between visual quality and numerical stability at different distances.

### The linear transformation

From a merely numerical standpoint, having either a linear or non-linear conversion makes no difference. Converting values among different reference frames is trivial if the conversion formulae are known. In the end, Z-values of any (visible) object are re-mapped to the \\$\[0, 1\]\\$ interval nonetheless. However, we must account for floating-point precision because computer numbers are discrete (more on that later).

The following linear function transforms the z-value to a depth value between `0.0` and `1.0`:

$$F\_{depth} = \frac{z - near}{far - near}$$

Here, \\$near\\$ and \\$far\\$ are the distances of the near and the far plane. The result is a linear mapping: you are 'scaling' and applying an offset to some values so that they fit a different scale range.

One property of values transformed with a linear function is, they keep their relative proportions. For example, if point \\$A\\$ is distant twice than \\$B\\$ from the camera (i.e. \\$A\_z = 2 B\_z ⇒ \frac{A\_z}{B\_z} = 2\\$), then the ratio is still the same when comparing their depth values.

This property holds because we are using the same precision for all values in the \\$\[0, 1\]\\$ interval:

### Discriminating close and distant objects

Using a linear transformation means using the same precision for *near* and *distant* values.

However, because of perspective projection, closer objects appear larger and farther ones smaller. Also, due to the parallax effect, closer objects appear to move faster when the camera moves around. Such an object's position on the screen will noticeably change even for small camera movements. On the other hand, when rendered, objects at a distance will barely move.

Sometimes, we can't represent such small changes due to floating-point precision. Some values are so close to each other a machine can't evaluate them, and an approximation is required. In 3D rendering, this happens because of depth buffer precision and causes Z-fighting.

> I think we can avoid the problem by doing the following.

Its very nature makes Z-fighting *unavoidable*. You can only mitigate its effects by using a different solution. And, these glitches mustn't show up near the camera.

Since closer objects are more susceptible to camera movement during rendering, we prioritise precision in the depth buffer for them. Then, we need to define a new mapping function that allocates more values for closer objects while using the remaining values for farther ones. Such a solution is a non-linear transformation.

### The multiplicative inverse transformation

Because of the above projection properties, we use a non-linear depth equation proportional to \\$1/z\\$. We cannot compare ratios via depth buffer values anymore: they were linear only before applying the projection matrix.

The following is the new formula:

$$F\_{depth} = \frac{\frac{1}{z} - \frac{1}{near}}{\frac{1}{far} - \frac{1}{near}}$$

It distributes value density in the \\$\[0, 1\]\\$ range differently from a linear equation:

> I suppose I could make it linear by doing the following, but why don't people do this?

The above function gives us *enormous* precision for very small z-values in comparison to a linear function: values between `1.0` and `2.0` would result in depth values between `1.0` and `0.5`, which is half of the \\$\[0,1\]\\$ range. Greater z-values will be stored using less precision over and over since they represent distant objects. This is acceptable: we can hide Z-fighting in the distance via fog effects, design choices (e.g. indoor environments), or even (almost) avoided by limiting the far plane distance and never overlapping surfaces and objects.

Alternate rendering techniques are also possible, such as rendering very far objects separately from the playable scene and displaying them in the background (this solution is implemented as pre-rendered cube maps in some space simulators such as SpaceEngine).

---

Reference: 'Depth testing' at *Learn OpenGL*, by Joey de Vries.
> 4 votes

# Answer
Because your formula breaks the depth interpolation.

Vertex shaders compute out the (x, y, z) values and w values. Then in an unprogrammable step, (x, y, z) is divided by w, and interpolated. In fragment shaders, you will only get interpolated z values. This interpolated z value is crucial for the depth test to get a correct render image.

Let's say we have two line segments, one is (-1, 0, -1)-(1, 0, -3) with red color, and the other one is (1, 0, -2)-(-1, 0, -2) with green color, and your camera look towards -z.

These two segments should intersect at (0, 0, -2). That is to say, you see red on the left(where x\<0), and green on the right(where x\>0).

How does your GPU know they intersect at x=0? It first has to do the perspective projection to the 4 vertices, and then interpolate the 4 depth values in window space. The x, y, z mapping from camera space to window space is carefully designed to make sure that the interpolated z value of the two line segments equals when x=0.

That's why z-mapping cannot be made linear.
> 0 votes

---
Tags: opengl, graphics-programming
---


# Question
Title: Can I develop games with Unity on cloud without installation?
I want to start game development, ideally I would only code with C# on Visual Studio with some Visual Studio extensions, without installing other extra software on my laptop.

As Unity seems to be the best choice for Game Dev, is there any chance to use it completely on the cloud without install any software (like a "SaaS – Software as a Service")?

# Answer
> 0 votes
I think you can by using virtual desktop cloud or cloud pc, but you need to install Unity and everything else needed on the cloud computer, and also install the software that is required to access the cloud computer on your laptop. **Disclaimer: I never tried it myself**. You also need to look at the latency, latency above 100ms might be frustrating to use, and it might also takes a lot of internet data, so be careful with it.

You may also need to install operating system on the cloud computer before you can use it (windows, linux, etc), which is difficult if you don't know how. But it is quite likely that this is going to change in the future where os installation will be easy, i don't see the reason why it won't.

Example of cloud pc : https://www.microsoft.com/en-us/windows-365

# Answer
> 0 votes
Unity development typically requires local installation due to resource-intensive tasks. However, cloud-based solutions like Unity Cloud Build allow collaboration and continuous integration without requiring the full Unity editor installation on each developer's machine.

---
Tags: unity
---


# Question
Title: Are moddable apps allowed in the Apple App Store?
While reading the App Store Review Guidelines, it was said :

> (iv) They may not download or install standalone apps, kexts, additional code, or resources to add functionality or significantly change the app from what we see during the review process.

Does this mean that moddable games are not allowed?

I want to add official mod support to my game. The mod will be executed in a protected environment where dangerous features are not allowed or restricted.

If the Apple App Store does not allow modding, then I will have no choice but to disable mod support for my app that is released on the App Store, and ask the user from within the game to install the app from outside the App Store directly from my website if they want to play the game with mod support enabled.

# Answer
> 2 votes
This isn't legal advice and I haven't published a moddable game in the Apple App Store.

Adding mod support appears to depend on how you implement it and possibly on the nature of your app. The following is taken from the Apple Developer Program License Agreement, Program Requirements, APIs and Functionality, Executable Code (section 3.3.1.B):

> Except as set forth in the next paragraph, an Application may not download or install executable code. Interpreted code may be downloaded to an Application but only so long as such code: (a) does not change the primary purpose of the Application by providing features or functionality that are inconsistent with the intended and advertised purpose of the Application as submitted to the App Store, (b) does not create a store or storefront for other code or applications, and (c) does not bypass signing, sandbox, or other security features of the OS.

The "next paragraph" mentioned pertains to an "application that is a programming environment intended for use in learning how to program."

So my read of this is:

* **Interpreted code** is allowed provided it doesn't:
    + change the nature of app
    + create a storefront that competes with the appstore
    + interfere with security.
* **Executable code** is allowed for **educational programming apps** but has additional requirements and restrictions (as listed in the documentation).

The guidelines are subject to interpretation, and usually Apple does the interpreting. If you do decide to pursue mod support for your game, I recommend making small, incremental changes.

I would also be very careful about asking users from within the game to install the app from outside the App Store directly from your website - you're essentially using the App Store to distribute your game and then directing users away from the App Store for additional content. Even if you're not charging for the mods, Apple gets to interpret whether or not that amounts to creating a storefront.

---
Tags: ios, modding, macos, appstore, ipad
---


# Question
Title: Web application for efficient placement of blocks
Task: to develop a function that efficiently places rectangular blocks in rectangular 2D container. The location of the blocks in the container should be as dense as possible in order to rationally use the space of the container.

I am almost done but I have some problems with my code: items overlap each other

Here is my code, but I don't want use some libraries:

```
<!DOCTYPE html>
<html>
<head>
  <title>Block Placement Algorithm</title>
  <style>
    .container {
      width: 500px;
      height: 500px;
      position: relative;
      border: 1px solid #ccc;
    }
    .block {
      position: absolute;
      border: 1px solid #000;
    }
  </style>
</head>
<body>
  <div class="container" id="container"></div>

  <script>
 function checkOverlap(newBlock, existingBlocks) {
  for (const block of existingBlocks) {
    if (
      newBlock.right >= block.left - blockMargin &&
      newBlock.left <= block.right + blockMargin &&
      newBlock.bottom >= block.top - blockMargin &&
      newBlock.top <= block.bottom + blockMargin
    ) {
      return true; // Якщо є перекриття з існуючим блоком
    }
  }
  return false; // Якщо немає перекриття з існуючими блоками
}

    function calculateBlockArea(blockCoordinates) {
      let totalBlockArea = 0;

      for (const block of blockCoordinates) {
        totalBlockArea += block.width * block.height;
      }

      return totalBlockArea;
    }

    // Generate block coordinates
    const blockCoordinates = [];
    const containerWidth = 500;
    const containerHeight = 500;
    const maxAttempts = 100;
    const blockMargin = 0;

    for (let i = 0; i < 10; i++) {
      const width = Math.floor(Math.random() * 100) + 50;
      const height = Math.floor(Math.random() * 100) + 50;

      let newBlock;
      let attempts = 0;
      do {
        newBlock = {
          top: Math.floor(Math.random() * (containerHeight - height)),
          left: Math.floor(Math.random() * (containerWidth - width)),
          right: 0,
          bottom: 0,
          initialOrder: i + 1,
          width: width,
          height: height
        };

        newBlock.right = newBlock.left + width;
        newBlock.bottom = newBlock.top + height;

        attempts++;
      } while (checkOverlap(newBlock, blockCoordinates) && attempts < maxAttempts);

      blockCoordinates.push(newBlock);
    }

    // Sort blocks by initialOrder
    blockCoordinates.sort((a, b) => a.initialOrder - b.initialOrder);

    // Render blocks on the page
    const container = document.getElementById('container');

    let currentTop = 0;
    let currentLeft = 0;

    blockCoordinates.forEach(block => {
      const div = document.createElement('div');
      div.className = 'block';
      div.style.width = block.width + 'px';
      div.style.height = block.height + 'px';

      // Set position based on the order with margin
      div.style.top = currentTop + 'px';
      div.style.left = currentLeft + 'px';
      div.textContent = block.initialOrder;

      const randomColor = "#" + ((1 << 24) * Math.random() | 0).toString(16);
      div.style.backgroundColor = randomColor;

      container.appendChild(div);

      currentLeft += block.width + blockMargin;
      if (currentLeft + block.width > containerWidth) {
        currentTop += block.height + blockMargin;
        currentLeft = 0;
      }
    });
  </script>
</body>
</html>

```

# Answer
> 1 votes
In your if statement:

```
if (currentLeft + block.width > containerWidth) {
  currentTop += block.height + blockMargin;
  currentLeft = 0;
}

```

you're setting the value of `currentTop` based on height of the current block that's causing the wrap.

Instead you need to know the max height of the first row's blocks for the x-axis range that the new block is covering. This pen works for the second row of blocks, but it needs to be further edited so that the 3rd+ row will work - Because the heights of the second row are all unique it isn't particularly straightforward to calculate the height of the third row.

https://codepen.io/TerabyteTiger/pen/eYXeObp?editors=1011

A lot of what I did could probably be abstracted out into functions, but I wanted to leave it all inline so that it's easier for you to review what I'm doing where. Good luck!

---
Tags: 2d, javascript, json, html, css
---


# Question
Title: Moving/Teleporting Local Volumetric Clouds in Unity
I'm currently using the Volumetric Clouds feature with the HDRP in Unity. My game world has gotten a little too big, so I'm trying to implement a "floating origin"-type system to fix floating-point glitches. The thing is, I'm using *local* clouds, which the player can actually move around. So when I shift all the game objects, I need to also be able to shift the clouds.

Is there any way to translate/move/teleport the clouds exactly as they are to a different location?

### Things I've tried

The **position property of the transform** doesn't seem to do anything (in either a local or global volume).

The closest easy option I can find is the **"shape offset"** property (disabled in image):

When I enable the **"Shape Offset"** override, I can sort of move the clouds around but they shift and change. I'm moving the "large noise" pattern around, but there is other noise at play that changes their shape, an that noise is not being offset.

I tried using the **wind** parameters to move the clouds, thinking that I could maybe set it fast enough to move the clouds a large distance in a single frame, but no matter how I tweaked the settings, the clouds still seem to change as they move. (In the clip below, the camera is moving with the clouds in the wind):

**"Cloud Map Offset"** seemed promising, but it too doesn't seem to work quite right. It seems to move the "areas" where clouds are or aren't, but it doesn't move the clouds themselves. So if there's an area where there currently isn't a cloud, and you use this to "offset" an existing cloud spot, instead of actually moving the existing cloud, a new, slightly different cloud appears in the offset position.

Anyone have any ideas on how to move the entire noise system to move all the clouds exactly as they are? Maybe some advanced setting I have figured out yet?

# Answer
> 1 votes
Since HDRP 17 it has feature to offset visual environment including volumetric clouds.

https://docs.unity3d.com/Packages/com.unity.render-pipelines.high-definition@17.0/manual/visual-environment-volume-override-reference.html#planet

This post on forum helped me to fix the same issue you had

https://forum.unity.com/threads/volumetric-clouds.1078811/page-16#post-9596413

Here is example how I used it

```
        if (!clonedVolumeProfile.TryGet(out VisualEnvironment visualEnvironment)) return;

        visualEnvironment.centerMode.value = VisualEnvironment.PlanetMode.Manual;

        // it is in km, but offset is meters, convert it
        visualEnvironment.planetCenter.value -= offset / 1000f;

```

# Answer
> 0 votes
~~You could try adding the opposite of your current speed vector to the clouds scrolling speed.~~

After experimenting I've come to the same conclusion as you. :(

My testing involved teleporting the camera to coordinates and changing the shapeoffset to match. Since the shapeoffset isn't in metres, I found the unit conversion by moving the camera and offset at different rates\*deltatime on the same axis until they both appeared to be standing still.

1m world space = ~0.00005f in cloud offset space.

The main 'cloud shapes' stay in the same relative positions, but the rest of the noise doesn't seem to be accessible.

I found this post from a dev saying that shape offset should be enough: https://forum.unity.com/threads/volumetric-clouds.1078811/page-10#post-7600129 \- so maybe some recent features have made this not possible to do.

The only ideas I have left are to try putting your own Cloud Map and Lut under Manual Cloud Control, and then see if the ShapeOffset and/or CloudMapOffset get nice results.
Could also try scrolling the texture UV's. (I wish I could test it but couldn't find out how to make those textures, or find pre-made ones)

---
Tags: unity, hdrp, clouds
---


# Question
Title: How can I convert .obj files into a 2D array of [x,y,z] coordinates and color values?
I have a cool 3D model I want to use, but for this program I'm working with, I need it in array form, with each point's coordinates and color value. I've already voxelized the model using this tool, but I'm not sure how to convert the voxelized .obj file into an array of coordinates and color values.

# Answer
Extract vertices and colors from voxelized OBJ file by iterating through voxels, matching to original model vertices, and storing results in an array.
> 0 votes

---
Tags: 3d, models, voxels, obj
---


title: Can RenderDoc debug linux binaries?

text:
# Question
Title: Can RenderDoc debug linux binaries?
I have downloaded RenderDoc for linux, but when passing a program as an argument it says "wrong file format", i have tried renaming to program.bin but same error. Is it a RenderDoc linux binary to debug only Windows app ?

# Answer
> 0 votes
RenderDoc mainly supports debugging Windows apps; Linux compatibility is limited and experimental. Use alternatives like GDB or Valgrind instead.

---
Tags: debugging
---


# Question
Title: Detecting Mesh Geometry Irregularities in Unity
I am trying to create a function to detect mesh geometry irregularities — for instance, the mesh possibly contains a missing face or possible normal flip problem.

To detect the missing face, I utilized some AI tools and found that:

```
bool HasMissingFaces(Mesh mesh)
{
    int[] triangles = mesh.triangles;
    int vertexCount = mesh.vertexCount;

    // Ensure that every index in triangles is within the valid range of vertices
    foreach (var index in triangles)
    {
        if (index < 0 || index >= vertexCount)
        {
            return true; // Missing face found
        }
    }

    return false; // No missing faces found
}

```

But this is not higlighting any problem in the mesh. What is the right way to detect missing face? **Edit:** Here are the picture demonstration. The house model front and back images given:

# Answer
> 0 votes
Unity is probably not the right place to be doing this kind of detection, if you can avoid it.

The reason is that DCC tools like 3ds Max / Maya / Blender maintain a lot of metadata about how a shape is constructed and how its parts connect together, to support powerful geometry modifying operations.

When those meshes get imported into a game engine, all that extra data gets baked/stripped away to make the leanest, most efficient version for rendering. So what we see in the game data structures is just a "polygon soup" — just a big array of vertex data and indices to indicate which vertex triples form each triangle. In that form, it's hard to answer "is this face oriented the same way as the ones it's touching" because we don't *know* which ones it's touching.

Rebuilding this adjacency information is somewhat complex to code, expensive to run, error-prone, and won't be able to recover all the info the DCC tool it was authored in had.

So, I'd only try to do this in Unity if it has to happen *dynamically*, e.g.

* Players / modders need to be able to import custom meshes at runtime, and have them pass a validation check or auto-correction before they can be used in-game.
* If you have a procedural content generation algorithm running inside Unity that occasionally produces bad geo. (Though there, a better solution is to fix the algorithm, since it likely has better info about what it's doing than the polygon soup you get at the end)

In all other circumstances, it's more effective to solve this in your DCC tool of choice. They'll often have specialized tools or user-made scripts for detecting/solving this kind of problem (at least, the subset where we can tell the difference between an intentional and unintentional hole/flip in some algorithmic way), and you may even be able to use their scripting API to run these tools on batches of models, rather than inspecting each one by hand.

---

If you need to do this in Unity, here's a high-level overview of the steps it would take.

1. Iterate over the vertices and group them by position. During import/export, any vertex point on the mesh where there's a hard/creased edge or a texture mapping seam will be split into multiple vertices sharing the same position. We need to find all those discrete vertex indices referring to the same point and map them to one "logical" vertex ID.
2. Iterate over all the triangle indices to note which logical vertices they connect, in what order. Build a collection of oriented edges and the faces they border, keyed by the logical vertex indices they connect (you can use the "half-edge" data structure for this).
3. Check through this collection for multiple edges sharing the same pair of vertices (in the same or opposite order):

* Only one edge connects this pair: this could be the border of a deliberate hole or "missing face" in your mesh. Or it could be on the outside border of a skirt mesh that doesn't close in on itself, like a ground plane. This can also occur if your mesh has T-junctions, where there's a "zero-width hole" between a big polygon and multiple smaller ones along a shared edge, but the surface looks unbroken.
    * Two edges connect this pair, with opposite orders: this is a "manifold" seam between two adjacent faces oriented the same way. This geo is probably fine.
    * Two edges connect this pair, with the same order: here we have two faces meeting but facing in opposite directions. It's very likely one of them is flipped relative to its neighbours.
    * Three or more edges: here you have non-manifold geometry with fins, and all bets are off as to what the artist intended here. You'll need manual inspection to determine whether it's as-desired.

Once you've found one of these edges at the border of a potential hole or flipped face, you can continue walking along connected edges to find which triangles are flipped relative to their neighbours (e.g. use the majority vote to determine which orientation is "right") or which triangles would need to be inserted to plug the hole, if your heuristics determine that it *is* a hole that needs plugging.

---
Tags: unity, c#, mesh
---


# Question
Title: Unity Camera snaps back to camera mouse look after lerping to a point and rotating normally. Once mouse look is re-enabled it overrides and snaps back
I am trying to get the camera to rotate towards a location and position. Which works at the moment, but once it is done and re enables the mouse look script or bool in the script the mouse look overrides the rotation and sets it back to the original rotation it had when the rotation started.

```
if (lockedOn)
    {
        // Get the direction to the target
        Vector3 direction = target.transform.position - transform.position;

        // Calculate the rotation to face the target
        Quaternion rotationToTarget = Quaternion.LookRotation(direction, Vector3.up);

        // Rotate towards the target over time
        transform.rotation = Quaternion.RotateTowards(transform.rotation, rotationToTarget, rotationSpeed * Time.deltaTime);

        if (currentFOV >= closeFOV)
        {
            curRotation = transform.rotation;
            currentFOV -= fovSpeed * Time.deltaTime;
            camera.fieldOfView = currentFOV;
        }
    }

    if (!lockedOn)
    {
        if (currentFOV <= startFOV)
        {
            currentFOV += fovSpeed * Time.deltaTime;
            camera.fieldOfView = currentFOV;
            transform.rotation = curRotation;

            if (camera.fieldOfView >= startFOV)
            {
                target = null;
                transform.localRotation = curRotation;
                mouseLook.lockControls = false;
            }
        }
    }
    if (removeFromCharacter)
    {
        // Distance moved equals elapsed time times speed..
        float distCovered = (Time.time - startTime) * cameraMoveSpeed;

        // Fraction of journey completed equals current distance divided by total distance.
        float fractionOfJourney = distCovered / journeyLength;

        // Set our position as a fraction of the distance between the markers.
        transform.position = Vector3.Lerp(origCameraLocation.transform.position, newCameraLocation.position, fractionOfJourney);
    }

```

and the mouse look script

```
 if(!lockControls)
    {
    // Get mouse input
    float mouseX = Input.GetAxis("Mouse X");
    float mouseY = Input.GetAxis("Mouse Y");

    // Rotate the player's body based on horizontal mouse movement
    playerBody.Rotate(Vector3.up * mouseX * sensitivity);

    // Calculate the new vertical rotation
    rotationX -= mouseY * sensitivity;
    rotationX = Mathf.Clamp(rotationX, -verticalLookLimit, verticalLookLimit);

    // Apply the rotations to the camera and player body
    transform.localRotation = Quaternion.Euler(rotationX, 0f, 0f);
    }

```

# Answer
> 1 votes
I went back and rewrote the script in the mouse look script instead of the `FollowLookAt` script. It is now working. Here is the script if anyone is trying to do the same:

```
public float sensitivity = 2.0f; // Adjust the sensitivity of mouse movement
public Transform playerBody;

public float verticalLookLimit = 90f; // Adjust the vertical look limit in degrees
private float rotationX = 0f;
public bool lockControls = false;
public GameObject targetObject;
public float movementTime = 1;
public float rotationSpeed = 0.1f;
public Transform origPostion;
public Quaternion origRotation;

public bool transitionIn;
public RemyMovementController remyMovementController;

float lookTimer;
public float lookTime = 5f;
private void Start()
{
    Cursor.lockState = CursorLockMode.Locked; // Lock the cursor to the center of the screen
}

private void Update()
{
    if (!lockControls)
    {

        // Get mouse input
        float mouseX = Input.GetAxis("Mouse X");
        float mouseY = Input.GetAxis("Mouse Y");

        // Rotate the player's body based on horizontal mouse movement
        playerBody.Rotate(Vector3.up * mouseX * sensitivity);

        // Calculate the new vertical rotation
        rotationX -= mouseY * sensitivity;
        rotationX = Mathf.Clamp(rotationX, -verticalLookLimit, verticalLookLimit);

        // Apply the rotations to the camera and player body
        transform.localRotation = Quaternion.Euler(rotationX, 0f, 0f);
    }
    else if (lockControls)
    {
        if (transitionIn)
        {
            lookTimer += Time.deltaTime;

            if (lookTimer > lookTime)
            {
                transitionIn = false;
                lookTimer = 0;
            }
            Quaternion targetRotation = Quaternion.LookRotation(targetObject.transform.position - transform.position);
            // Smoothly rotate towards the target point.
            transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);
        }
        else if (!transitionIn)
        {
            transform.rotation = Quaternion.Slerp(transform.rotation, origRotation, rotationSpeed * Time.deltaTime);
            if (transform.rotation == origRotation)
            {
                UnTrackObject();
            }
        }
    }
}

public void TrackObject()
{
    lockControls = true;
    transitionIn = true;
    remyMovementController.enabled = false;
    origRotation = transform.rotation;
    origPostion = transform;
}

public void TransitionOut()
{
    transitionIn = false;
}

public void UnTrackObject()
{
    lockControls = false;
    remyMovementController.enabled = true;
}

```

With this script it allows the camera to rotate towards an object while locking the controls and then rotate back to the original position then unlock the controls.

# Answer
> 0 votes
You can add something like this to your mouse look script, so it inherits the current orientation when re-enabled:

```
void OnEnable() {
    // Get current facing direction.
    var look = transform.forward;

    // Convert to spherical coordinate angles:
    float yaw = Mathf.Atan2(look.x, look.z) * Mathf.Rad2Deg;
    float pitch = Mathf.Asin(-look.y) * Mathf.Rad2Deg;

    // Rotate player to account for yaw component:
    playerBody.rotation = Quaternion.Euler(0, yaw, 0);

    // Store current pitch, and apply it.
    rotationX = pitch;
    transform.localRotation = Quaternion.Euler(rotationX, 0, 0);
}

```

---
Tags: unity, c#, rotation, mouse
---


# Question
Title: Tracking real life object in Virtual Reality
I'm building a VR game (in Unity) in which a user uses a real-life steering wheel to drive around. I want them to be able to grab the steering wheel in real life, while the virtual counter part of this steering wheel is located on the 'correct' location in the VR headset. I.e. if the steering wheel is located half a meter from the VR headset in real-life, it is placed half a meter from the user's point of view in the simulation.

How can I make sure of this, without asking the user to play around with settings? Ideally, I would want the headset to be able to detect and locate the real-life steering wheel, and relay this location to my software. The software would then simply place the steering-wheel in the correct location.

I found some old forum-posts (~2016) talking about IR trackers, but I couldn't really find anything definitive. I am using a Meta Quest 3, which does have cameras, so it might be able to detect some sort of (IR) tracker? What would be a good method of doing this?

# Answer
> 0 votes
If your object is static non-moving, You can use Meta scene understanding to identify an object in their list, query for it in your application to find the location of the object and its bounding box. Meta currently doesn't have a solutions for computer vision related tasks for identifying real world objects because they don't allow camera stream.

This blog does a good job in describing scene understanding

I Would identify the steering wheel as a plant set the bounding box around the wheel, then in my unity app query for the plant to get the location.

---
Tags: virtual-reality, meta-quest
---


title: Accurate fps cap?

text:
# Question
Title: Accurate fps cap?
Simple question, how do I *limit* the games fps in Unity?

I know there's Application.TargetFPS and whatnot, but it doesn't actually cap it. It just tries to get it.

Vsync also wouldn't work, because you should be able to cap fps without having to enable vsync, also if I use vsync I wouldn't be able to cap the fps to a custom value, say 23.

# Answer
> 3 votes
It sounds like you have some sort of misunderstanding.

`Application.targetFramerate` sets the framerate that Unity tries to run at.

* If the current device is not capable of running at the desired framerate, then the actual FPS will be lower.
* If the device is more powerful than is needed to run at the desired FPS, Unity will attempt to limit the framerate to the target framerate (in other words, cap it). Depending on the device and how you're measuring the framerate, the framerate may sometimes fluctuate slightly higher than the target, but not by a significant amount.

Make sure you read the documentation thoroughly because there are several important quirks and differences between platforms.

So in summary, you can use `Application.targetFramerate` to cap the framerate, unless you're on one of the platforms where `targetFramerate` is ignored if you have Vsync enabled (in which case Vsync will cap the framerate). If you are seeing unexpected behavior, the first thing to check is whether there are any scripts that might be changing the target framerate.

I often use `targetFramerate` to cap the framerate in the Editor, so my GPU isn't running at max power at all times when Vsync is off.

---
Tags: unity
---


title: Camera code in polar coordinates

text:
# Question
Title: Camera code in polar coordinates
I have OpenGL code for camera:

```
static float  angleX = 180;
static float angleY = 0;

POINT mousexy;
GetCursorPos(&mousexy);

int xt=400;
int yt=300;

angleX +=(xt - mousexy.x)/7.0f;
angleY +=(yt - mousexy.y)/7.0f;

if (angleY<-89.0){angleY=-89.0;}
if (angleY>89.0){angleY=89.0;}

SetCursorPos(xt,yt);

static vector3 vPos = vector3( 25.0, 5.0, 5.0);

float PI = 3.1415926f;
float speed = 25.0f;
float dx,dy,dz;
dx = dy = dz = 0.0f;

if(GetAsyncKeyState('W')& 0xFF00)
    {
        dx =- sin(angleX/180*PI) * speed;
         dz =- cos(angleX/180*PI) * speed;
    }

    if(GetAsyncKeyState('S')& 0xFF00)
    {
        dx = sin(angleX/180*PI) * speed;
         dz = cos(angleX/180*PI) * speed;
    }

    if(GetAsyncKeyState('D')& 0xFF00)
    {
        dx = sin((angleX+90)/180*PI) * speed;
         dz = cos((angleX+90)/180*PI) * speed;
    }

    if(GetAsyncKeyState('A')& 0xFF00)
    {
        dx = sin((angleX-90)/180*PI) * speed;
         dz = cos((angleX-90)/180*PI) * speed;
    }

    vPos.x += dx*fElaspedAppTime;
    vPos.y += dy*fElaspedAppTime;
    vPos.z += dz*fElaspedAppTime;

    vector3 vLook;
    vLook.x = vPos.x - sin(angleX/180*PI);
    vLook.y = vPos.y + tan(angleY/180*PI);
    vLook.z = vPos.z - cos(angleX/180*PI);

    gluLookAt(vPos.x, vPos.y, vPos.z,
        vLook.x, vLook.y, vLook.z,
        0.0f, 1.0f, 0.0f);

    MeshManager.Draw_Mesh();

```

Code above works fine for OpenGL. I tried to transfer this code to my software rendering project (software triangle rasterization, perspective correct texture mapping) but camera is not woring properly. This is my code from softrend project (below):

```
matrix4x4 CMeshManager::Get_View_Matrix()
{
    float Time = Get_Elapsed_Time();

    UINT ScreenWidth = m_ViewWidth;
    UINT ScreenHeight = m_ViewHeight;

    POINT MousePos;
    GetCursorPos(&MousePos);

    SetCursorPos(ScreenWidth/2, ScreenHeight/2);

    static float DeltaX = 180;
    static float DeltaY = 0;

    DeltaX -=(( float(ScreenWidth/2)-MousePos.x) / 12.0f);
    DeltaY +=(( float(ScreenHeight/2)-MousePos.y) / 12.0f);

    float speed = 25.0f;
    float dx,dy,dz;
    dx = dy = dz = 0.0f;

    if(GetAsyncKeyState('W')& 0xFF00)
    {
        dx = -sin(DeltaX/180*PI) * speed;
         dz = -cos(DeltaX/180*PI) * speed;

    }

    if(GetAsyncKeyState('S')& 0xFF00)
    {
        dx = sin(DeltaX/180*PI) * speed;
         dz = cos(DeltaX/180*PI) * speed;

    }

    if(GetAsyncKeyState('D')& 0xFF00)
    {
        dx = sin((DeltaX-90)/180*PI) * speed;
         dz = cos((DeltaX-90)/180*PI) * speed;

    }

    if(GetAsyncKeyState('A')& 0xFF00)
    {
        dx = sin((DeltaX+90)/180*PI) * speed;
         dz = cos((DeltaX+90)/180*PI) * speed;
    }

    m_VecPos.x += dx * Time;
    m_VecPos.y += dy * Time;
    m_VecPos.z += dz * Time;

    m_VecLook.x = -sinf(DeltaX/180*PI);
    m_VecLook.y = tanf(DeltaY/180*PI);
    m_VecLook.z = -cosf(DeltaX/180*PI);

    m_VecLook = Vec3_Normalize(m_VecLook);
    m_VecUp = Vec3_Cross(m_VecLook,m_VecRight);
    m_VecUp = Vec3_Normalize(m_VecUp);
    m_VecRight = Vec3_Cross(m_VecUp,m_VecLook);
    m_VecRight = Vec3_Normalize(m_VecRight);

    float xp = -Vec3_Dot(m_VecPos, m_VecRight);
    float yp = -Vec3_Dot(m_VecPos, m_VecUp);
    float zp = -Vec3_Dot(m_VecPos, m_VecLook);

    matrix4x4 MatView = matrix4x4(
        m_VecRight.x, m_VecUp.x, m_VecLook.x, 0,
        m_VecRight.y, m_VecUp.y, m_VecLook.y, 0,
        m_VecRight.z, m_VecUp.z, m_VecLook.z, 0,
        xp,       yp,    zp,      1 );

    return MatView;
}

```

Where I am wrong?

# Answer
> 0 votes
```
matrix4x4 CMeshManager::Get_View_Matrix()
{
    float Time = Get_Elapsed_Time();

    UINT ScreenWidth = m_ViewWidth;
    UINT ScreenHeight = m_ViewHeight;

    POINT MousePos;
    GetCursorPos(&MousePos);

    SetCursorPos(ScreenWidth/2, ScreenHeight/2);

    static float DeltaX = PI;
    static float DeltaY = 0;

    DeltaX -= (float(ScreenWidth/2)-MousePos.x) / 800;
    DeltaY -= (float(ScreenHeight/2)-MousePos.y) / 800;

    if (DeltaY<-PI/2.0f){DeltaY=-PI/2.0f;}
    if (DeltaY>PI/2.0f){DeltaY=PI/2.0f;}

    static vector3 m_VecPos = vector3( 25.0, 5.0, 5.0);

    float speed = 25.0f;
    float dx,dy,dz;
    dx = dy = dz = 0.0f;

    if(GetAsyncKeyState('W')& 0xFF00)
    {
        dx = -sin(DeltaX) * speed * Time;
        dz = -cos(DeltaX) * speed * Time;
    }

    if(GetAsyncKeyState('S')& 0xFF00)
    {
        dx = sin(DeltaX) * speed * Time;
        dz = cos(DeltaX) * speed * Time;
    }

    if(GetAsyncKeyState('D')& 0xFF00)
    {
        dx = sin(DeltaX-PI/2.0f) * speed * Time;
        dz = cos(DeltaX-PI/2.0f) * speed * Time;
    }

    if(GetAsyncKeyState('A')& 0xFF00)
    {
        dx = sin(DeltaX+PI/2.0f) * speed * Time;
        dz = cos(DeltaX+PI/2.0f) * speed * Time;
    }

    m_VecPos.x += dx;
    m_VecPos.y += dy;
    m_VecPos.z += dz;

    vector3 m_VecUp = vector3(0.0f, 1.0f, 0.0f);
    vector3 m_VecRight, m_VecLook;

    m_VecLook.x = -sin(DeltaX);
    m_VecLook.y = -tan(DeltaY);
    m_VecLook.z = -cos(DeltaX);

    m_VecLook = Vec3_Normalize(m_VecLook);
    m_VecRight = Vec3_Cross(m_VecUp,m_VecLook);
    m_VecRight = Vec3_Normalize(m_VecRight);
    m_VecUp = Vec3_Cross(m_VecLook,m_VecRight);
    m_VecUp = Vec3_Normalize(m_VecUp);

    float xp = -Vec3_Dot(m_VecPos, m_VecRight);
    float yp = -Vec3_Dot(m_VecPos, m_VecUp);
    float zp = -Vec3_Dot(m_VecPos, m_VecLook);

    matrix4x4 MatView = matrix4x4(
        m_VecRight.x, m_VecUp.x, m_VecLook.x, 0,
        m_VecRight.y, m_VecUp.y, m_VecLook.y, 0,
        m_VecRight.z, m_VecUp.z, m_VecLook.z, 0,
        xp,       yp,    zp,      1 );

    return MatView;
}

```

Sorry for fuss, I fixed code, just should made local vars (not global):

```
    vector3 m_VecUp = vector3(0.0f, 1.0f, 0.0f);
    vector3 m_VecRight, m_VecLook;

```

This vars was global vars, and it cause problems.

And first should made cross product with VecUp and VecLook, then VecRight.

---
Tags: c++
---


title: Unity UI Builder InvalidCastException

text:
# Question
Title: Unity UI Builder InvalidCastException
I am making a custom UI with the UI Builder for my scriptable object that holds some data for the AI Player. It all worked fine until I added a third slider for a new value I needed; now the object won't preview in the inspector and I get an `InvalidCastException` for no reason. The sliders are for floats, and the values in the scriptable object are also floats, and the custom objects I am using for a list was working too, and I didn't change it at all. I tried debugging it by removing all data bindings in the builder so that it just renders the UI without any data, but it still gives the same error even though no data is being bound...

```
[CustomEditor(typeof(AiBrainData))]
    public class AiControllerDataEditor : Editor
    {
        private const string path = "UI/AI/ai_brain_data";

        public override VisualElement CreateInspectorGUI()
        {
            VisualTreeAsset vta = (VisualTreeAsset)Resources.Load(path);
            VisualElement root = new();
            vta.CloneTree(root);

            return root;
        }
    }

[CreateAssetMenu(menuName = "AI/Brain")]
    public class AiBrainData : ScriptableObject
    {
        [SerializeField] private BrainFeature[] _features;
        public BrainFeature[] BrainFeatures => _features;

        [SerializeField, Range(1f, 0f)] private float _reductionFactor = 0.5f;
        public float ReductionFactor => 1f - _reductionFactor;

        [SerializeField, Range(0f, 10f)] private float _increasionAmount = 0.5f;
        public float IncreasionAmount => _increasionAmount;

        [SerializeField, Range(0f, 5f)] private float _normalizationStep = 2.5f;
        public float NormalizationStep => _normalizationStep;
    }

<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
    <Style src="project://database/Assets/Resources/UI/AI/ai_brain_data.uss?fileID=7433441132597879392&guid=65086b2200eb7e14eb6c4612fdf51cb5&type=3#ai_brain_data" />
    <ui:VisualElement name="root">
        <ui:Label text="Brain Features" name="title" style="margin-left: 4px; margin-right: 4px; margin-top: 4px; margin-bottom: 4px; -unity-font-style: normal; font-size: 14px; -unity-text-align: upper-center;" />
        <ui:ListView focusable="false" name="items" picking-mode="Ignore" header-title="Brain Features" show-bound-collection-size="false" virtualization-method="DynamicHeight" binding-path="_features" view-data-key="_features" style="margin-bottom: 4px; background-color: rgb(202, 202, 202); border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(176, 176, 176); border-right-color: rgb(176, 176, 176); border-top-color: rgb(176, 176, 176); border-bottom-color: rgb(176, 176, 176); padding-top: 4px; padding-right: 8px; padding-left: 2px; padding-bottom: 2px;" />
        <ui:Slider picking-mode="Ignore" label="Reduction" value="0.5" high-value="0" name="reduction" show-input-field="true" tooltip="The reduction factor for a feature outcome." low-value="1" binding-path="_reductionFactor" class="slider_brain" />
        <ui:Slider picking-mode="Ignore" label="Increasion" value="5" high-value="10" name="increasion" show-input-field="true" focusable="true" binding-path="_increasionAmount" class="slider_brain" />
        <ui:Slider picking-mode="Ignore" label="Normal Step" value="2.5" high-value="5" name="normal" tooltip="The step at which a reduced feature is normalized to it's weight." show-input-field="true" focusable="true" binding-path="_normalizationStep" class="slider_brain" />
    </ui:VisualElement>
</ui:UXML>

```

The error just points to the `CreateInspectorGUI` method in the `AiControllerDataEditor` class.

# Answer
> 0 votes
The problem was that I created a style sheet with the same name, and the script was trying to cast it to a VisualTreeAsset which is supposed to be a uxml file...

---
Tags: unity, c#, unity-ui
---


# Question
Title: How to prevent sun light from passing through the walls and flickering when navigating in viewport?
I am new to UE5. I am using a geometry brush to create an inner box and an outer box. The inner is set to **brush type ‘subtractive’**, resulting in a simple room like this:

Then I create several windows using the same subtractive way:

Now the sunlight behaves very weirdly: **it passes through the solid wall** and **flickers** when I navigate or rotate my camera view.

This is absolutely some glitch, but I don’t know how to fix this so that the sun light behaves more stably instead of coming and going unexpectedly when navigating in the room.

How can I fix this?

# Answer
Looking at this other thread, it would appear that Lumen does not work very well with brushes. Most people recommend transforming the brush into a static mesh to avoid this issues.

Alternatively, to quickly create a room you can use the meshes available in the starter content pack. To add the starter pack to an existing project, look at the top left of your Content Browser window and you will see an `Add` button with a green plus icon. Click that and then select `Add Feature or Content Pack...`. This will add to your project a number of things, including some basic meshes to create rooms. You can also get meshes from Quixel Bridge.

Finally, I don't know what the goal of your project is nor am I a professional developer, but from my understanding brush editing (and the Modeling tool) are used to prototype levels to quickly test them or make a proof of concept (PoC). In these scenarios, lighting does not need to be perfect so the behaviour you are seeing would not matter much (though it would of course be incorrect for a shipped game).
> 0 votes

---
Tags: lighting, unreal-5, csg
---


# Question
Title: Normalized coordinates not translating to screen coordinates the way I need them to
I am making a simple game in C# using pictureboxes. I want to move a picturebox on a form. Once this picturebox is placed in a new location, I normalize its X,Y coordinates between \[0, 1\] and then send them to a server. The server does nothing but broadcast those normalized coordinates to all of the connected clients.

Once a client gets the normalized coordinates from the server, it translates them back into screen coordinates so it knows where to place the picturebox. This allows the picturebox to display in the correct spot for both screens, even if the screen sizes are very different.

Here is the code that shows how this process is done: https://pastebin.com/1igRRtKJ

If both screens are the exact same size (specifically if the form sizes I am testing with are the same) then this process works perfectly. However, if one screen size is different than the other (specifically, the form sizes are greatly different) then they don't display quite right.

If one image is placed to be next to another on the small screen, the big screen will show a ton of spacing between them that shouldn't exist. Likewise, if the big screen moves an image to sit next to another one, the small screen will show them overlapping each other which should not happen.

Here are some screenshots illustrating the problem: https://imgur.com/a/y2NTHm3 and https://imgur.com/a/oIV5Huy

Given the code I shared and the problem I am describing, how can I fix this issue? I'd like the pictureboxes to show up in the exact same position on all of the client's screens, even if they are vastly different from each other.

I'm fairly certain the math here is correct. So, I am unsure what the actual problem is. When the screen sizes are different the images will appear approximately where they should go, but not exactly. I'd like to somehow maintain the relative distance, which I thought this would do, but clearly I am missing something. I set the pictureboxes using the location method, which is based on the top-left corner of the picturebox.

Normalize coordinates (client sending the normalized coordinates of the moved image):

```
normalizedX = picturebox.location.x / (client_width - picturebox.width);
normalizedY = picturebox.location.y / (client_height - picturebox.height);

```

Translate coordinates (clients getting the normalized coordinates):

```
adjustedX = normalizedX * (client_width - picturebox.width);
adjustedY = normalizedY * (client_height - picturebox.height);

```

I'd really love to solve this problem. I have asked this question in several different places, but no one seems to be able to help.

# Answer
The idea of creating a consistent coordinate system between all of the clients was definitely the right idea and my original implementation was correct. The problem was that the images also needed to be scaled relative to the screen size in order to maintain their ratios. Additionally, the program needed to maintain its aspect ratio so that the scaled images would have the correct position and distance for all screen sizes.

With this information in mind, I designed the program to have its initial dimensions be a 16:9 ratio. I still allow users to resize the form, but only from one of the four corners, so that they are forced to update both the height and width when manually resizing the form. Doing all of this ensured that the program was always in a 16:9 ratio (or at least close enough that the distance and positions of images were still really accurate).

So, in summary, if you read the original question and want to achieve the same results, you can think of this as a three step process:

1. Create a consistent coordinate system between clients
2. Scale your images in relation to the screen size
3. Force your program to maintain the supported aspect ratio

Here is a simplified version of the code for each of the three steps so you should be able to follow along and get this working pretty easily.

Normalize coordinates before sending to other clients:

```
double actualX = pb.Location.X;
double actualY = pb.Location.Y;

double percentageX = actualX / (ClientRectangle.Width - pb.Width);
double percentageY = actualY / (ClientRectangle.Height - pb.Height);

```

Translate the normalized coordinates to screen coordinates:

```
double adjustedX = percentageX * (ClientRectangle.Width - pb.Width);
double adjustedY = percentageY * (ClientRectangle.Height - pb.Height);

```

Scale images (pictureboxes in my case):

```
// For the reference size I used the default program height/width
double scaleFactor = Math.Min(this.Width / referenceWidth, this.Height / referenceHeight);

// Scale from the original image size
pb.Width = originalWidth;
pb.Height = originalHeight;

// This will work for both scaling up and down
pb.Width = (int)Math.Round(pb.Width * scaleFactor);
pb.Height = (int)Math.Round(pb.Height * scaleFactor);

```

Maintain aspect ratio:

This isn't something I technically enforced with code. I just recommend designing your program to be in a 16:9 aspect ratio by default and then attempt to enforce this the best you can. I am sure there is a good way to do this, but I just took the easy way out and did as I described above.

This is why the problem was so tricky for me to figure out, because it was not just one single thing causing the problem. It was a combination of them all. So, my original question only really took care of 1/3 of the problem, which is why I just couldn't get it to work the way I wanted. Once I completed the other two steps, things work exactly how I wanted them to.
> 2 votes

---
Tags: mathematics, graphics, multiplayer, coordinates
---


# Question
Title: Do I always need to call SaveAssets & Refresh after calling AssetDatabase.CreateAsset?
I'm working with `AssetDatabase.CreateAsset` and all over the internet (not so much in the official documentation) I see

```
AssetDatabase.CreateAsset(blah, blahPath);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();

```

Why?

`SaveAssets` says it *Writes all unsaved asset changes to disk* so I assume that there's a situation in which you can have changes to your assets in memory, but not on disk. Is this the case when you create an asset with `CreateAsset`? I tried ending the Unity process right after creating a file but it looks like it writes to disk immediately, but I've only tried in-editor on Windows. Maybe it behaves differently in runtime or on different platforms.

`Refresh` says it *will import any assets that have changed their content modification data or have been added-removed to the project folder*. The editor UI gets updated when I call CreateAsset even if I don't Refresh, so is this for updates from other sources, or what?

I'm trying to understand the process and not do things *just because everyone does it like that*.

# Answer
Unity lacks clarity in its documentation on when to use different AssetDatabase methods. That's why a lot of people call all the available methods after an asset change just to be sure.

Robert C. Martin provides a good piece of advice in his "Clean Code" book: When you are not sure how API works, write unit tests for it. Not only will you learn how to use it, but when there are new releases, just running those tests again will detect if there are changes you should know of.

That's what I did, and you can run those tests on your machine too: https://gist.github.com/SolidAlloy/3027f88e69b63700b9ae530360cfd0eb

Here is what I discovered:

* `CreateAsset()` and `ImportAsset()` add the file to AssetDatabase automatically, so you don't have to call any other methods.
* `AssetDatabase.Refresh()` is only needed when a file was added through System.IO (like `File.WriteAllText()`). Without it, you will not be able to get the asset GUID or load a `Unity.Object` from the asset.
* `AssetDatabase.SaveAssets()` is only needed when you made changes to a `Unity.Object` instance (e.g. `ScriptableObject`), marked the object as dirty, and want to see the changes written to disk. Unity Editor writes all the changes to disk upon exit, so the use of `SaveAssets()` is very limited. It is only helpful when you changed a scriptable object and want to open the .asset file in a text editor and see the changes there without closing the editor.

I also discovered a weird bug/feature that may cause a lot of headaches if you are not aware of it:
If you create an asset and then remove it, AssetDatabase will store the deleted asset GUID and path until the Editor closes. No method can remove the GUID from the database.
> 8 votes

# Answer
To add some details to the already great answer:

* Using SaveAssets is overstepping your boundaries!

Call SaveAssetIfDirty (since Unity 2020) with your asset path instead. Leave the other unsaved assets alone, other scripts or the user need to take care of them. They may not want them to be saved to begin with.

* NO AssetDatabase method requires calling Refresh afterwards. EVER!

SaveAssets and Refresh are being appended to way too many AssetDatabase methods ONLY out of habit, following a ritual, a cargo cult. STOP DOING THAT!

Refresh is only needed when a file or folder was modified outside the AssetDatabase **AND** you cannot possibly know which file(s)/folder(s) were modified.

Typically you DO know EXACTLY what was modified. In that case, you call ImportAsset for each modified file/folder.

The AssetDatabase methods are very unfortunately named. Refresh should have been called "CheckAllAssetFilesForModificationsAndThenUnloadUnusedResources". Just to be in line with the usual length of AssetDatabase names. I called mine "ImportAll".

Refresh's issue is that it goes over each file in your project to check if one has been added, modified or removed! This naturally takes time. More so, the more assets you have in the project.

Refresh also calls "unload unused resources" internally so any asset that is loaded (cached) in memory but currently not referenced gets unloaded. The next time you click on an asset in the project view or a script that calls LoadAsset will have to load that asset from disk rather than using the cached instance.

Problem is: the scripts get usually created in simple projects or early on. Especially tool developers never get to experience, and profile, their scripts on actual user projects. Then users of big projects get to suffer and complain about how slow Unity is. Neither side even THINKS about the cause being inefficient editor scripts because everyone is so used to seeing SaveAsset + Refresh in every script.

I made a video about such incorrect AssetDatabase uses and what they do to editor performance. I found even worse examples than I could have imagined.

I also rewrote the entire AssetDatabase to hopefully end this crud. At the least look at the test cases. They all succeed without a single call to Refresh.
> 1 votes

---
Tags: unity
---


# Question
Title: How to install a Steam demo you're developing?
When you own a game, Steam doesn't show you the demo to install it. But when you're developing the demo, you want to install it for testing.

Is it possible to get Steam to install my unreleased demo?

# Answer
The docs say to create test accounts that don't own the game and grant them special keys. However, there is another way.

To run an unreleased demo you need to have a dev account with sufficient permissions. However, even with those permissions, the demo doesn't show up by default. You need to use something like Ashark's method.

Figure out your appid and use it below instead of DEMO\_APPID. This will be **different** from your main game and you can find it on the partner site next to the name of the demo.

Paste these instructions into Slack/Discord to share with your team (message yourself with them and test they work first!):

1. Click steam://open/console
2. That should open the Console tab in Steam. In there, run: `app_install DEMO_APPID`
3. You should now see the demo in Steam's Downloads. If you got a permissions error, you need our Steamworks admin to add permissions to your account.

*This answer condenses Ashark's great answer for players into something targeted to devs.*
> 2 votes

---
Tags: steam, demo
---


title: How do I make volumetric grass?

text:
# Question
Title: How do I make volumetric grass?
I've been extremely interested in volumetric technology, especially for grass.

Online resources are extremely scarce on this topic.

What is the difference from creating a lot of mesh billboards? Is this shader based technology or simply a geometry type of generator? How do I create something like this?

# Answer
> 1 votes
Not sure what you mean by volumetric rendering of grass, can't tell the volume from the picture, but if that's the kind of thing you're talking about then you can search for "shell based fur rendering" and there'll be plenty of info on it

It's essentially a geometry shader that generates a multi-layer mesh, and samples a 3d noise texture as density for each layer, and then achieves something like "volume".

This method is equivalent to rendering the mesh many times over than a billboard, and there is an additional overhead with geometry shader, as well, as there are distortions when sampling step is too low, which I'm not sure can be solved by post-processing, such as low-sampling + blurring.

---
Tags: c#, shaders, rendering, graphic-effects
---


title: Uniforms management

text:
# Question
Title: Uniforms management
I wanted to know if there is any special optimization going on with uniforms and shaders. The issue I'm facing is that when increasing an uniform which is clamped to an option by a modulo, it only works with odd numbers. As if the uniform was set twice and skipped a frame. if uniform management strictly implementation dependent or does opengl try to cache it ? I'm asking this question since I'm working on a program that I did not code myself for implementing clipmaps voxelization. And the only way I don't get alternating voxelization (clearly visible level 0, 1 ... being voxelized one after the other) is by modifying the index in the function that sets the uniform for the shaders.

# Answer
> 0 votes
It turns out that each meshes sets uniforms, and since I increase the level in the function that sets the uniforms, the lod increases by the number of object for each frame. And even worst, uniforms are set for each vertex...

---
Tags: glsl
---


# Question
Title: It's possible to use more than 4 channels of a texture in GLSL?
I have a Texture with 6 channels. Each channel store a mask that is used to change a color of a part of my player's sprite.

When the texture only had 3 channels it was easy to implement this color change using a shader, but the only way I can think of how to do it with 6 channels is using 2 textures (which seems pretty annoying to me).

It's possible to use a 6 channel texture nativity in GLSL?

# Answer
> 3 votes
Using multiple textures is the standard way this is done, and GPUs are well adapted to that use. We store all sorts of things in textures, not just colours and masks.

That doesn't mean you have to *work* with multiple textures, of course. If it makes sense to you, just add some middle-ware that converts the multi-channelled texture into an appropriate set of textures, so you can author the textures in a way that's convenient for you. Though again, the tooling also tends to work with one- or four-channel textures for the most part.

# Answer
> 8 votes
The maximum for a single texture is four channels in every GPU rendering API that I know.

While it's technically possible to encode more data into those four channels (e.g. storing eight 4-bit values, instead of four 8-bit values), you'll run into two main problems with that:

1. The standard hardware texture filtering won't work with your encoded data. This means you'll have to use point sampling, decode the data in the shader, and do manual texture filtering on top of that, if you need it.
2. The standard texture compression formats (ASTC, ETC2, PVRTC etc.) won't understand the encoded data either, so you'll probably end up using more memory than two separate compressed textures because it'll need to be stored uncompressed.

Using two textures is probably your best solution here.

---
Tags: shaders, textures, glsl
---


# Question
Title: Collapse/uncollapse a Tree in Godot 4 by clicking on the TreeItem?
Is there a way to collapse/uncollapse a `Tree` (Control) in Godot 4 by clicking on the `TreeItem` instead of the folding arrow?

I mean, I click on an item, gets selected and the subitems get uncollapsed. Click again the same item and the subitems get collapsed.

I've managed to achieve a similar behaviour by connecting the `item_selected()` signal from the `Tree`, but it just doesn't work flawlessly:

* Some mouse clicks are missed if you click quick (less quick than a double-click though).
* The selected item must be deselected because **the signal won't trigger again if the item is already selected**, and I'd like the item to be shown as selected.

Here's the code:

```
@onready var characters_tree: Tree = $MarginContainer/Tree

func _on_tree_item_selected() -> void:
    var item := characters_tree.get_selected()
    item.collapsed = not item.collapsed
    item.deselect(0)

```

# Answer
> 1 votes
Connect to the Tree's `item_mouse_selected` signal, which is emitted when an item is selected with a mouse button. It is even emitted again if the item is already selected, so you don't have to deselect it in your code.

```
func _on_tree_item_mouse_selected(position, mouse_button_index):
    var item = characters_tree.get_selected()
    item.collapsed = not item.collapsed

```

However, if you click twice fast enough to be considered a double-click, this signal is not emitted for the second click. Instead the `item_activated` signal is emitted. You mentioned that your quick clicks were less quick than a double-click, but double-clicks can be deceptively long and still register as one. To account for this, you should also connect to the `item_activated` signal.

```
func _on_tree_item_activated():
    var item = characters_tree.get_selected()
    item.collapsed = not item.collapsed

```

---
Tags: gui, godot, godot-4
---


title: Infinite jump issue

text:
# Question
Title: Infinite jump issue
I am currently making a game in c++ using sfml, I encountered a problem where if I jump in my game, the jump mechanic allows the player to jump repeatedly in mid-air which is something I do not want. Here is a video showing my issue. I believe there is either an issue with my bool or collision but I am not sure what it is. Here is my player.h player.cpp and game.cpp.

player.h

```
#pragma once
#include "Precomp.h"

enum PLAYER_ANIMATION_STATES { Idle = 0, Left_Move, Right_Move, Jumping };

class Player
{

private:
    sf::Sprite sprite;
    sf::Texture textureSheet;
    sf::Clock animationTimer;

    //Animation
    short animationStates;
    sf::IntRect currentFrame;
    bool animationSwitch;

    //Physics
    sf::Vector2f velocity;
    sf::Vector2f position = sprite.getPosition();
    float x;
    float y;
    float maxVelocity;
    float minVelocity;
    float acceleration;
    float drag;
    float gravity;
    float MaxYVelocity;
    float time;
    float jumpVelocity;
    float maxJumpHeight;
    bool isJumping = false;
    bool canJump = true;

    //Health Points

    //Private functions
    void initVariables();
    void initTexture();
    void initSprite();
    void initAnimations();
    void initPhysics();

public:
    Player();
    virtual ~Player();

    //Accessors
    const bool& getAnimationSwitch();
    const sf::Vector2f getPosition();
    const sf::FloatRect getGlobalBounds() const;
    const sf::Sprite& getSprite() const;

    //Modifiers
    void setPosition(const float x, const float y);
    void resetVeloictyY();
    void resetVelocityX();

    //Functions
    void resetAnimationTimer();
    void move(const float dir_x, const float dir_y);
    void setPlayerHitbox();
    void updatePhysics();
    void update();
    void updateAnimations();
    void updateMovement();
    void render(sf::RenderTarget& target);

};

```

player.cpp

```
include "Player.h"

void Player::initVariables()
{
    this->animationStates = PLAYER_ANIMATION_STATES::Idle;
}

void Player::initTexture()
{
        //lLoad a texture
        if (!this->textureSheet.loadFromFile("Sprites and Textures/Kim Pine Full Sprite Sheet 3.png"))
        {
            std::cout << "Failed";
        }
}

void Player::initSprite()
{
    //Set the texture to the sprite

    this->sprite.setTexture(this->textureSheet);

    //Resize the sprite
    this->sprite.scale(3.f, 3.f);
    this->currentFrame = sf::IntRect(0, 0 , 48, 95);
    this->sprite.setTextureRect(this->currentFrame);
}

void Player::initAnimations()
{
    this->animationTimer.restart();
    this->animationSwitch = true;

}

void Player::initPhysics()
{
    this->maxVelocity = 10.f;
    this->minVelocity = 1.f;
    this->acceleration = 1.05f;
    this->drag = 0.96f;
    this->gravity = 4.f;
    this->MaxYVelocity = -15.f;
    this->time = 1.f;
    this->jumpVelocity = -12.0f;

}

Player::Player()
{
    this->initVariables();
    this->initTexture();
    this->initSprite();
    this->initAnimations();
    this->initPhysics();

}

Player ::~Player()
{

}

const bool& Player::getAnimationSwitch()
{
    bool anim_switch = this->animationSwitch;

    if (this->animationSwitch)
        this->animationSwitch = false;

    return anim_switch; //Have not documented this yet as I have not fixed the animation yet
}

const sf::Vector2f Player::getPosition()
{
    return this->sprite.getPosition();
}

const sf::FloatRect Player::getGlobalBounds() const
{
    return this->sprite.getGlobalBounds();
}

const sf::Sprite& Player::getSprite() const
{
    return this->sprite;
}

void Player::setPosition(const float x, const float y)
{
    this->sprite.setPosition(x, y);
}

void Player::resetVeloictyY()
{
    this->velocity.y = 0.f;
}

void Player::resetVelocityX()
{
    this->velocity.x = 0.f;
}

void Player::updateAnimations()
{
    if (this->animationStates == PLAYER_ANIMATION_STATES::Idle)
    {
        if (this->animationTimer.getElapsedTime().asSeconds() >= 0.25f || this->getAnimationSwitch())
        {
            this->currentFrame.top = 0.f;
            this->currentFrame.left += 49.25f;
            if (this->currentFrame.left >= 147.75f)
                this->currentFrame.left = 0;

            this->animationTimer.restart();
            this->sprite.setTextureRect(this->currentFrame);
        }
    }
    else if (this->animationStates == PLAYER_ANIMATION_STATES::Right_Move)
    {

        if (this->animationTimer.getElapsedTime().asSeconds() >= 0.1f || this->getAnimationSwitch())
        {
            this->currentFrame.top = 92.0f;
            this->currentFrame.left += 49.1f;
            if (this->currentFrame.left >= 245.9f)
                this->currentFrame.left = 0;

            this->animationTimer.restart();
            this->sprite.setTextureRect(this->currentFrame);

        }
        this->sprite.setScale(3.f, 3.f);
        this->sprite.setOrigin(0.f, 0.f);
    }
    else if (this->animationStates == PLAYER_ANIMATION_STATES::Left_Move)
    {

        if (this->animationTimer.getElapsedTime().asSeconds() >= 0.1f || this->getAnimationSwitch())
        {
            this->currentFrame.top = 92.0f;
            this->currentFrame.left += 49.1f;
            if (this->currentFrame.left >= 245.9f)
                this->currentFrame.left = 0;

            this->animationTimer.restart();
            this->sprite.setTextureRect(this->currentFrame);

        }
        this->sprite.setScale(-3.f, 3.f);
        this->sprite.setOrigin(this->sprite.getGlobalBounds().width / 3.f, 0.f);
    }
    /*
    else if (this->animationStates == PLAYER_ANIMATION_STATES::Jumping)
    {
        if (this->animationTimer.getElapsedTime().asSeconds() >= 0.1f || this->getAnimationSwitch())
        {
            this->currentFrame.top = 196.0f;
            this->currentFrame.left += 59.8f;
            if (this->currentFrame.left >= 778.f)
                this->currentFrame.left = 0;

            this->animationTimer.restart();
            this->sprite.setTextureRect(this->currentFrame);

        }
        this->sprite.setScale(3.f, 3.f);
        this->sprite.setOrigin(0.f, 0.f);
    }
    */
    else
    {
        this->animationTimer.restart();
    }
}

void Player::updateMovement()
{
        //Move Player
        this->animationStates = PLAYER_ANIMATION_STATES::Idle;

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::A) || sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Left))
    {
        this->move(-1.f, 0.f);
        this->animationStates = PLAYER_ANIMATION_STATES::Left_Move;

    }
    else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::D) || sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Right))
    {
        this->move(1.f, 0.f);
        this->animationStates = PLAYER_ANIMATION_STATES::Right_Move;

    }
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::W) || sf::Keyboard::isKeyPressed(sf::Keyboard::Space) || sf::Keyboard::isKeyPressed(sf::Keyboard::Up) && canJump)
    {
            this->velocity.y = jumpVelocity;
            this->canJump = false;
            this->animationStates = PLAYER_ANIMATION_STATES::Jumping;

            if (sf::Event::KeyReleased)
            {
                if (this->velocity.y < -12.f)
                    this->velocity.y = -12.f;
            }

    }
        /*
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::S) || sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
        {
            this->sprite.move(0.f, 1.f);

        }
    */
}

void Player::resetAnimationTimer()
{
    this->animationTimer.restart();
    this->animationSwitch = true;
}

void Player::move(const float dir_x, const float dir_y)
{
    //Accceleration
    this->velocity.x += dir_x * this->acceleration;

    //Limit Velocity
    if (std::abs(this->velocity.x) > this->maxVelocity)
    {
        this->velocity.x = this->maxVelocity * ((this->velocity.x < 0.f) ? -1.f : 1.f);
    }

}

void Player::updatePhysics()
{
    /*
    //Gravity
    this->velocity.y += 1.0 * this->gravity;
    if (std::abs(this->velocity.y) > this->MaxYVelocity)
    {
        this->velocity.y = this->MaxYVelocity * ((this->velocity.y < 0.f) ? -1.f : 1.f);
    }
    */

    //Deceleration
    this->velocity *= this->drag;

    //Limit Deceleration
    if (std::abs(this->velocity.x) < this->minVelocity)
        this->velocity.x = 0.f;
    if (std::abs(this->velocity.y) < this->minVelocity)
        this->velocity.y = 0.f;

    this->sprite.move(this->velocity);
    this->velocity.y += gravity * time;

    //Jump Gravity

    /*
    if (canJump)
    {
        this->velocity.y = 0.f;
        this->canJump = true;
    }
    */

    if (this->sprite.getPosition().y + this->sprite.getGlobalBounds().height >= 600)
    {
        this->canJump = false;
        this->velocity.y = 0.f;
        this->sprite.setPosition(this->sprite.getPosition().x, 600 - this->sprite.getGlobalBounds().height);

    }

}

void Player::update()
{
    this->updateMovement();
    this->updatePhysics();
    this->updateAnimations();

}

void Player::setPlayerHitbox()
{

}

void Player::render(sf::RenderTarget& target)
{
    target.draw(this->sprite);

    sf::CircleShape circ;
    circ.setFillColor(sf::Color::Red);
    circ.setRadius(2.f);
    circ.setPosition(this->sprite.getPosition());

    target.draw(circ);

};

```

game.cpp

```
#include "Game.h"

//Private Functions

void Game::initPlayer()
{
    this->player = new Player();
}

void Game::initPlatform()
{
    sf::RectangleShape platform(sf::Vector2f(200.f, 20.f));
    platform.setPosition(300.f, 500.f);
    platform.setFillColor(sf::Color::White);
}

void Game::initVariables()
{

}

void Game::initWindow()
{
    this->window.create(sf::VideoMode(800,600), "CFFA Window", sf::Style::Titlebar | sf::Style::Close);
    this->window.setFramerateLimit(144);

}

//Constructors

Game :: Game()
{
    this->initVariables();
    this->initWindow();
    this->initPlayer();

}

Game ::~Game()
{

    delete this->player;
}

const bool Game::running() const
{
    return this->window.isOpen();
}

//Accessors

//Functions

void Game::render()
{
    /*
        return void

        - clears the old frame
        - renders the new objects
        - displays the frame in the new window

        Renders the game objects
    */

    this->window.clear();

    //Draw game objects
    this->renderPlayer();

    this->window.display();
}

void Game::update()
{
    //Event Polling
    while (this->window.pollEvent(this->ev))
    {
        if (this->ev.type == sf::Event::Closed)
        {
            this->window.close();
        }
        else if (this->ev.type == sf::Event::KeyPressed && this->ev.key.code == sf::Keyboard::Escape)
        {
            this->window.close();
        }
        if (this->ev.type == sf::Event::KeyReleased &&
            (this->ev.key.code == sf::Keyboard::D ||
                this->ev.key.code == sf::Keyboard::A ||
                this->ev.key.code == sf::Keyboard::W ||
                this->ev.key.code == sf::Keyboard::S
                )
            ) // Need to Document when animation fixed

            this->player->resetAnimationTimer();
    }

    this->updatePlayer();
}

void Game::renderPlayer()
{
    this->player->render(this->window);
}

const sf::RenderWindow & Game::getWindow() const
{
    // TODO: insert return statement here
    return this->window;
}

void Game::updatePlayer()
{
    this->player->update();
    this->updateCollision();
}

void Game::updateCollision()
{
    //Collision with Window
    if (this->player->getPosition().y + this->player->getGlobalBounds().height > this->window.getSize().y)
    {
        this->player->resetVeloictyY();
        this->player->setPosition(this->player->getPosition().x, this->window.getSize().y - this->player->getGlobalBounds().height);
    }
    if (this->player->getPosition().x + this->player->getGlobalBounds().width > this->window.getSize().x)
    {
        this->player->resetVelocityX();
        this->player->setPosition(this->window.getSize().x - this->player->getGlobalBounds().width, this->player->getPosition().y);
    }
    if (this->player->getPosition().x < 0)
    {
        this->player->resetVelocityX();
        this->player->setPosition(0, this->player->getPosition().y);
    }
    //Check collision between objects

}

```

Any help would be appreciated, thank you!

# Answer
Your problem is pretty easy to spot. It is located at this line of code.

```
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W) || sf::Keyboard::isKeyPressed(sf::Keyboard::Space) || sf::Keyboard::isKeyPressed(sf::Keyboard::Up) && canJump)

```

So what is the problem.

If we seperate this `if` statement into the seperate parts we have:

`if (isKeyPressed('w')`

`if (isKeyPressed('Space')`

`if (isKeyPressed('Up') && canJump`

Do you see the problem?

I recommend changing this code in 2 ways.

1. Wrap things in parenthesis properly, also simplify your `if` statements.
2. Check canJump first to shortcut all of the other checks. (No need to check if a key is pressed if the character cannot jump).

```
// This will be inlined and have no performance hit whatseover...
// and is less prone to errors/ allows you to easily change your implementation
// to allow for player key mapping...
inline bool jumpKeyPressed() {
   return sf::Keyboard::isKeyPressed(sf::Keyboard::W) || sf::Keyboard::isKeyPressed(sf::Keyboard::Space) || sf::Keyboard::isKeyPressed(sf::Keyboard::Up)
}
...

if (canJump && jumpKeyPressed()) {
    enter code here
}

```
> 1 votes

---
Tags: c++, sfml, jumping
---


title: Implementing a Fixed Time Step?

text:
# Question
Title: Implementing a Fixed Time Step?
This has been bugging me for few days now. I'm trying to stop movement jittering in my game. I've looked towards semi and fixed time steps - moving towards the latter below so I can really understand (as I hope to create multiplayer games in future).

I have a very basic set up with a ball that moves at a constant speed, unless the user tries to control it by pressing P to takeover. It's currently got a hard-coded 60 FPS value. When the accumulated time reaches that, the update is called and the ball is moved.

My issue is that I get occasional stuttering during movement and I really can't grasp why. Is there anything you guys would recommend to better what I have below?

Thank you in advance!

```
#include <iostream>
#include <SFML/Graphics.hpp>

int main() {
    sf::RenderWindow window(sf::VideoMode(1920, 1080), "Ping Pong");
    // window.setFramerateLimit(60);
    // window.setKeyRepeatEnabled(false);

    sf::Font font;
    font.loadFromFile("arial.ttf");

    sf::Text text;
    text.setFillColor(sf::Color::Green);
    text.setCharacterSize(72);
    text.setFont(font);
    text.setString("hello: ");

    sf::CircleShape circle;
    circle.setRadius(20.0f);
    circle.setOrigin(circle.getRadius(), circle.getRadius());
    circle.setPosition(window.getSize().x/2, window.getSize().y/2);

    float TIME_PER_FRAME = 1.0f / 60.0f;

    sf::Clock clock;
    float lastFrameTime = clock.getElapsedTime().asSeconds();
    float frameStartTime;

    float frameTime;
    float accumulator;

    int updateCount;
    bool movable = false;

    while(window.isOpen()) {
        updateCount = 0;

        frameStartTime = clock.getElapsedTime().asSeconds();

        frameTime = frameStartTime - lastFrameTime;
        accumulator += frameTime;

        lastFrameTime = frameStartTime;

        // events
        sf::Event event;
        while(window.pollEvent(event)) {
            if (event.type == sf::Event::KeyPressed) {
                if (event.key.code == sf::Keyboard::Escape) {
                    window.close();
                }
                //make ball controllable by player
                if (event.key.code == sf::Keyboard::P) {
                    movable = (movable) ? false : true;
                }
            }
        }

        // update
        while (accumulator >= TIME_PER_FRAME) {
            //character movable by WASD
            if (movable) {
                if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) {
                    circle.move(sf::Vector2f(200*TIME_PER_FRAME,0));
                }
                if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) {
                    circle.move(sf::Vector2f(-200*TIME_PER_FRAME,0));
                }
                if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) {
                    circle.move(sf::Vector2f(0,-200*TIME_PER_FRAME));
                }
                if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) {
                    circle.move(sf::Vector2f(0,200*TIME_PER_FRAME));
                }
            }

            //automated movement to the right
            if (!movable) {
                circle.move(sf::Vector2f(200*TIME_PER_FRAME,0));
            }

            //if ball goes off the right of the screen, appear on the left side
            sf::Vector2f c_position = circle.getPosition();
            if (c_position.x - circle.getRadius() > window.getSize().x) {
                circle.setPosition(sf::Vector2f(0-circle.getRadius(), c_position.y));
            }

            accumulator -= TIME_PER_FRAME;
            updateCount++;
        }

        //render
        window.clear();
        window.draw(circle);
        window.draw(text);
        window.display();

        std::cout << "updated " << updateCount << std::endl;
    }

    return 0;
}

```

EDIT:

I've had a look since the original implementation and the suggested interpolation steps. I tried initially to update the accumulator only in the while loop, interpolating (updating with the interpolating) afterwards but made little progress.

Since then I've created a simple player class and only interpolating on the rendering. This hasn't resolved it either. Below are my attempts:

main.cpp

```
#include <iostream>
#include <SFML/Graphics.hpp>
#include "player.cpp"

sf::Vector2f linearInterpolation(sf::Vector2f start, sf::Vector2f end, float alpha) {
    return (start * (1 - alpha) + end * alpha);
}

sf::Vector2f addTwoVectors(sf::Vector2f v1, sf::Vector2f v2) {
    return sf::Vector2f(v1.x + v2.x, v1.y + v2.y);
}

int main() {
    sf::RenderWindow window(sf::VideoMode(1920, 1080), "Ping Pong");
    window.setFramerateLimit(1000000);
    // window.setKeyRepeatEnabled(false);

    sf::Font font;
    font.loadFromFile("arial.ttf");

    sf::Time time;

    sf::Text text;
    text.setFillColor(sf::Color::Green);
    text.setCharacterSize(72);
    text.setFont(font);
    text.setString("hello: ");

    sf::CircleShape circle;
    circle.setRadius(20.0f);
    circle.setOrigin(circle.getRadius(), circle.getRadius());
    circle.setPosition(window.getSize().x/8, window.getSize().y/2);

    Player player = Player(window);

    const float speed = 2.0f;

    float TIME_PER_FRAME = 1.0f / 60.0f;

    sf::Clock clock;
    float lastFrameTime = clock.getElapsedTime().asSeconds();
    float frameStartTime = 0;

    float frameTime = 0;
    float accumulator = 0;
    float lastaccumulator = 0;

    float alpha = 0;

    int updateCount = 0;
    int nonUpdateCount = 0;
    bool movable = false;

    while(window.isOpen()) {
        frameStartTime = clock.getElapsedTime().asSeconds();
        frameTime = frameStartTime - lastFrameTime;

        lastaccumulator = accumulator;
        accumulator += frameTime;

        lastFrameTime = frameStartTime;

        // events
        sf::Event event;
        while(window.pollEvent(event)) {
            if (event.type == sf::Event::KeyPressed) {
                if (event.key.code == sf::Keyboard::Escape) {
                    window.close();
                }
                //make ball controllable by player
                if (event.key.code == sf::Keyboard::P) {
                    movable = (movable) ? false : true;
                }
            }
        }

        // update
        while (accumulator > TIME_PER_FRAME) {
            player.update();
            std::cout << "----------- updated one frame -----------" << std::endl;
            std::cout << "player position: " << player.getPosition().x << ", " << player.getPosition().y << std::endl;
            accumulator -= TIME_PER_FRAME;
        }

        alpha = accumulator / TIME_PER_FRAME;
        std::cout << "\n";
        std::cout << "accumulator: " << accumulator << std::endl;
        std::cout << "alpha: " << alpha << std::endl;

        //render
        window.clear();
        player.draw(alpha);
        window.draw(text);
        window.display();
    }

    return 0;
}

```

player.cpp

```
#include <SFML/Graphics.hpp>

class Player {
    private:
        sf::RenderWindow& window;
        sf::Vector2f speed;

        sf::CircleShape circle;
        sf::CircleShape i_circle;
    public:
        Player(sf::RenderWindow& window) : window(window) {
            this->speed = sf::Vector2f(5.0f, 0);

            circle.setRadius(20.0f);
            circle.setOrigin(circle.getRadius(), circle.getRadius());

            i_circle.setRadius(20.0f);
            i_circle.setOrigin(i_circle.getRadius(), i_circle.getRadius());

            sf::Vector2f middleOfScreen = sf::Vector2f(window.getSize().x/2, window.getSize().y/2);
            circle.setPosition(middleOfScreen);
        };
        ~Player() {};

        sf::Vector2f getPosition() {
            return circle.getPosition();
        }

        void update(){
            this->circle.move(speed);

            //if ball goes off the right of the screen, appear on the left side
            sf::Vector2f c_position = circle.getPosition();
            if (c_position.x - circle.getRadius() > window.getSize().x) {
                sf::Vector2f newPosition = sf::Vector2f(0-circle.getRadius(), c_position.y);
                circle.setPosition(newPosition);
            }
        };

        void draw(float interpolate) {
            i_circle.setPosition(circle.getPosition() + speed*interpolate);
            std::cout << "i_circle pos: " << i_circle.getPosition().x << ", " << i_circle.getPosition().y << std::endl;
            window.draw(i_circle);
        };
};

```

If you have any ideas, I'd appreciate the help, thank you!

# Answer
Implement continuous input, remove automated movement, and properly handle edge collisions to reduce jittering in ball movement. Use correct delta time calculation for consistent movement speed.
> -1 votes

---
Tags: c++, sfml, fixed-timestep
---


# Question
Title: Software rendering - compose View matrix
There is function compose View Matrix, it's software rendering project. Used fixed point math. phd\_sin() and phd\_cos() user defined functions implement sin() and cos(). Please explain this calculations, where is there vector Right, Up, Look, like in View matrix from DX for example? How composed View matrix in this case (below)? I dont know this approach.

typedef struct PHD_3DPOS {
    int32_t x;
    int32_t y;
    int32_t z;
    int16_t x_rot;
    int16_t y_rot;
    int16_t z_rot;
} PHD_3DPOS;

#define W2V_SHIFT 14

#define TRIGMULT2(A, B) (((A) * (B)) >> W2V_SHIFT)
#define TRIGMULT3(A, B, C) (TRIGMULT2((TRIGMULT2(A, B)), C))

typedef struct PHD_MATRIX {
    int32_t _00;
    int32_t _01;
    int32_t _02;
    int32_t _03;
    int32_t _10;
    int32_t _11;
    int32_t _12;
    int32_t _13;
    int32_t _20;
    int32_t _21;
    int32_t _22;
    int32_t _23;
} PHD_MATRIX;

#define MAX_MATRICES 40

PHD_MATRIX m_MatrixStack[MAX_MATRICES] = { 0 };

PHD_MATRIX g_W2VMatrix = { 0 };

void phd_GenerateW2V(PHD_3DPOS *viewpos)
{
    int32_t sx = phd_sin(viewpos->x_rot);
    int32_t cx = phd_cos(viewpos->x_rot);
    int32_t sy = phd_sin(viewpos->y_rot);
    int32_t cy = phd_cos(viewpos->y_rot);
    int32_t sz = phd_sin(viewpos->z_rot);
    int32_t cz = phd_cos(viewpos->z_rot);

    m_MatrixStack[0]._00 = TRIGMULT3(sx, sy, sz) + TRIGMULT2(cy, cz);
    m_MatrixStack[0]._01 = TRIGMULT2(cx, sz);
    m_MatrixStack[0]._02 = TRIGMULT3(sx, cy, sz) - TRIGMULT2(sy, cz);
    m_MatrixStack[0]._10 = TRIGMULT3(sx, sy, cz) - TRIGMULT2(cy, sz);
    m_MatrixStack[0]._11 = TRIGMULT2(cx, cz);
    m_MatrixStack[0]._12 = TRIGMULT3(sx, cy, cz) + TRIGMULT2(sy, sz);
    m_MatrixStack[0]._20 = TRIGMULT2(cx, sy);
    m_MatrixStack[0]._21 = -sx;
    m_MatrixStack[0]._22 = TRIGMULT2(cx, cy);
    m_MatrixStack[0]._03 = viewpos->x;
    m_MatrixStack[0]._13 = viewpos->y;
    m_MatrixStack[0]._23 = viewpos->z;
    g_W2VMatrix = m_MatrixStack[0];
}

```

# Answer
> 1 votes
The code snippet which you posted defines 3D positions and matrices along with helper functions `phd_sin()` and `phd_cos()` for trigonometric operations using fixed-point arithmetic. The function `phd_GenerateW2V()` generates a World-to-View transformation matrix based on given Euler angles **(x\_rot, y\_rot, z\_rot)** representing rotation around the X, Y, and Z axes respectively. The resulting W2V matrix stores the translation component (view position) and three orthogonal basis vectors: Right, Up, and Looking direction (which corresponds to Forward in typical coordinate systems). These basis vectors are computed using sine and cosine values derived from the input rotations. The generated matrix is stored in the global variable **g\_W2VMatrix**.

---
Tags: c++, mathematics
---


# Question
Title: How to go about executing lua scripts in a ECS engine?
I'm trying to add scripting with lua to my C++ game engine, and I'm pretty stumped on how to tackle the executing/processing part. I started by creating a `ScriptManager` which is responsible for preparing sol2 and eventually any binding stuff. Next, since I'm using ECS I created a `ScriptComponent` which stores the path to the script, and this where I'm stumped.

I suppose the next step would be to execute the scripts attached to entities, but I don't think I want to just loop through entities and execute the script over and over I probably want to execute it once and then call like Update(). An alternative approach I can think of would be to have the `ScriptManager` listen to events and call the appropriate lua functions, but I feel like the `ScriptSystem` is the better solution.

I know there's a plethora of ways to go about this, so I'm not trying to look for for a one size fits all solution just trying to gather some suggestions on how I could or how others do it.

# Answer
If your game engine is based on the ECS paradigm, then it could make sense if that paradigm is represented in the scripting system as well.

Which would mean that Lua is used to define and implement systems and the (non-standard) components those systems operate on.

For example, if the NPC "Bob" requires a script to have him patrol between the points A and B, then you would have a Lua script that defines both a "BobTheNPCComponent" (which might be created implicitly in case that the system does not need to store any data in it), as well as a "BobTheNPCSystem" that operates on all entities with the components `Position` and `BobTheNPCComponent`. Then the content designer who wants to assign that script to the Bob Entity would do so by assigning the script-defined "BobTheNPCComponent" to that entity, which will then cause that entity to be processed by the scripted "BobTheNPCSystem".

How could the script bindings for that look?

You basically need two C++-implemented functions exposed to the Lua scripting context:

* `registerComponent` that takes a string for the name of the component and a table describing its members.
* `registerSystem` that takes a table of component names, a LUA callback function to execute for each entity with all those components and (if that's part of your ECS architecture) a parameter that says when that system is executed (once, every update, on specific events, or whatever).

The Lua script containing those function calls would be executed once and then call those functions to register its system. The C++ side would then create the corresponding systems and components and call the callback function passed to `registerSystem` for each entity and pass the component tuple to it.
> 0 votes

---
Tags: c++, architecture, lua, entity-component-system
---


title: Why is Y up in many Games?

text:
# Question
Title: Why is Y up in many Games?
I learned at school that the z-axis is up. It is the same in modeling software like Blender. However in many games the y-axis is up.

What is the reason?

# Answer
I think the direction of the coordinate axes are holdovers from different domains where the crucial plane was different, and X/Y were aligned with that crucial plane. In some applications the ground plane was the most important, thus X/Y were the ground and Z ended up perpendicular to that. For games however the crucial plane is usually the screen (especially of course back when they were 2D and just starting to transition to 3D) thus X/Y were the screen and then when games went 3D Z ended up perpendicular to that.

You can see that kind of distinction between the two biggest 3D art tools: 3ds max and Maya. The Z axis is up in 3ds max because that grew out of architectural tools, while the Y axis is up in Maya because that grew out of movie-making tools.

The important thing to realize when comparing any specific tool to what you learned in school is that it's all arbitrary. It really doesn't matter which way the axes are pointed as long as you keep everything consistent and translate correctly between different coordinate systems.

EDIT: relevant tweet from Tim Sweeney lol https://twitter.com/timsweeneyepic/status/952661474501111808
> 60 votes

# Answer
As far as I have ever gleaned the Y = up/down, and Z = depth is based off of physics where gravity is **always** in the (-Y) direction, and then adding 3D means you don't want to change a **fundamental**, so it was made depth.

On the Z = up/down method though that is a throw back to mathematicians. because X/Y was drawn on the paper that was flat on the table when the Z-axis was extended it was coming up out of the paper, and therefore up. though many of your engineers will also use this convention as well.

in regards to the convention used by the given tool: Maya, and Unity have Y-up (probably designed by someone with a physics background). while 3DsMax, and Unreal have Z-up (probably designed by mathematicians/engineers). though it can also be said that these could also be just a split decision made one day because a consistent system had to be used.

since this question focuses on a modelling tool, and is placed on a gamedevelopment Q&A site. you might want to look into what coordinate system you will be exporting to, and make sure that you conform to that.

also realize that some system the axis system is hard set, and permanent, and others it can be modified (think it can be changed in Blender and Unreal, but might be mistaken)
> 6 votes

# Answer
It's mostly legacy from the times when all that could've been made with 3D was some screen-space rotating cube or parallax scrolling or something similar. In such applications, Z was "depth" because X and Y were the axes for the screen plane. As demos were getting more advanced, the original conventions stayed because it's easier not to change anything that works.

As for why exactly today's games have Y as the vertical axis - there are lots of poorly written tutorials out there that do not explain the difference. Usually it's most useful to have the primary movement plane on X and Y axes (so that most 2D calculations don't require swapping axes in code). For most sidescrollers, it is quite naturally coincident to the screen plane (X/Y). For adventure games and such, X/Y works nice as the horizontal plane (perpendicular to direction of gravity) because it maps perfectly to in-game maps, gamepad controls, terrain heightmaps and many other things.
> 3 votes

# Answer
Because the coordinate system that are used in games are based off of the dimension of the monitor. When computer renders anything, it starts at the upper left hand corner which gives the x, and y coordinate of \[ 0, 0 \]. As the rendering progresses towards the right side of the screen, the x value increments, respectively when the render moves down, the y value increments. The coordinate system is basically that of a 2D space, except the origin rest on the upper left hand corner and not the center of your screen.

In 3D packages such as 3DsMax and Maya, they have their own definition of x and y coordinates based on what is is important to them. 3DsMax was based off architectural design, if you draw a schematic on a 2D plane, y is up. In Maya, which is mainly use for animation therefore the ground is x, y and the height is z.
> 2 votes

# Answer
in all truth Frankie Law and snake4 gave the correct answer together if you think about it. The monitor itself is already in the xz plane not the xy plane. However, 2d started programming it all as xy, even though the correct direction would have been xz, unless your monitor is sitting flat on the ground, facing up, and your looking straight down at it, from directly above it. In which case it would be correct.

to clarify for those who need it: xyz has existed in physics and math longer than 3d graphics. And as 2d graphics started they only used two dimensions with no intention of adding a third at that time, so x and y. By the time a third dimension was added, simply adding it as the missing dimension was easier than rewriting years of work to put x, y, and z in their proper perspectives. So now we have two definitions that will never agree: on the one hand z is depth, or distance forward/backword, on the other z is altitude or up/down.

To complicate it even more for game development, before 3d graphics, in "top-down" games it was still x and y on the screen where y was not used as up, in 2d by "side scrollers" it was still x and y and here y was clearly used as up. So for game development which is height or depth depends on perspective.
> -5 votes

---
Tags: graphics, coordinates, view, orientation, axis
---