# Question
Title: Where to Save Health on Character with Behavior Tree - UE5
I've looked but havn't been able to find a the workflow for this searching online.

I have an NPC, with a behavior tree. Right now it just moves around the map. It's supposed to have a health variable, which triggers something to happen when its health is at 0. 'Health' is reduced when the player shoots a ray cast at it.

I'm unable to find where/how to place this.

I've tried storing the 'health' in the Character, the Controller, and in a Blackboard.

Storing it in the Blackboard allows the behavior tree 'Tasks' to modify it, but then it can't be triggered to change by an 'On Any Damage' in the NPC Character/Controller. I can put it in the Character, but then the tree or its tasks can't seem to access it.

Sorry if this is vague, I'm lost. This feels like it should be simple.

---

TLDR, all I need is a variable stored in the NPC Character which the behaviour tree or its tasks can react to. Simple, no? Can't figure out how personally.

# Answer
> 1 votes
Add the variable to the 'Character' blueprint, and add a variable of the same type to the tree's blackboard. In the 'task', cast to the Character blueprint the variable is stored in and use a 'Set Blackboard value as...' to make that value accessible to the behaviour tree.

---
Tags: ai, data-structure, unreal-5
---


# Question
Title: How to make a concisely, elegantly, and human-friendly Quaternion camera?
I have spent three weeks struggling with the quaternion camera!

Now I have two Implementations. **One has some kind of gimbal lock issue or something like that. Another one is totally anti-human** ( I feel like I am using a ZBrush camera to play a game).

**the faulty one:**

**the zbrush and anti-human one:**

**key codes of that two cameras:**

**the faulty one:**

```
void MouseInput(GLfloat xOffset, GLfloat yOffset, bool constrainPitch = 0) {
        xOffset *= turnSpeed;
        yOffset *= turnSpeed;

        if (glm::abs(glm::fmod(pitch, 360.0f)) < 90.0f || glm::abs(glm::fmod(pitch, 360.0f)) > 270.0f)
            yaw += xOffset;
        else
            yaw -= xOffset;

        pitch += yOffset;

        if (constrainPitch)
        {
            ...
        }
    }

```

```
void Update() {

        glm::quat qPitch = glm::angleAxis(glm::radians(-pitch), glm::vec3(1.0f, 0, 0));
        glm::quat qYaw = glm::angleAxis(glm::radians(-yaw), glm::vec3(0, 1.0f, 0));
        glm::quat qRoll = glm::angleAxis(glm::radians(roll), glm::vec3(0, 0, -1.0f));

        orientation = glm::normalize(qYaw * qPitch * qRoll);

        front = glm::normalize(orientation * glm::vec3(0, 0, -1.0f));
        up = glm::normalize(orientation * glm::vec3(0, 1.0f, 0));
        right = glm::normalize(orientation * glm::vec3(1.0f, 0, 0));

        fps = ViewMatrix();
        tps = ViewMatrixOrbital();
    }

```

**the zbrush and anti-human one:**

```
void MouseInput(GLfloat xOffset, GLfloat yOffset) {
        xOffset *= turnSpeed;
        yOffset *= turnSpeed;

        yaw = xOffset;
        pitch = yOffset;
    }

```

```
void Update() {
        glm::quat qYaw = glm::angleAxis(glm::radians(-yaw), up);
        glm::quat qPitch = glm::angleAxis(glm::radians(-pitch), right);
        glm::quat qRoll = glm::angleAxis(glm::radians(roll), front);

        orientation = glm::normalize(qRoll * qPitch * qYaw * orientation);

        front = glm::normalize(orientation * glm::vec3(0, 0, -1.0f));
        up = glm::normalize(orientation * glm::vec3(0, 1.0f, 0));
        right = glm::normalize(orientation * glm::vec3(1.0f, 0, 0));

        fps = ViewMatrix();
        tps = ViewMatrixOrbital();

                //Clear Everything
        yaw = 0;
        pitch = 0;
        roll = 0;
    }

```

**The view matrix functions of both of them are the same:**

```
    glm::mat4 ViewMatrix() {
        glm::mat4 translate = glm::translate(glm::mat4(1.0f), position);
        glm::mat4 rotate = glm::mat4_cast(orientation);
        return glm::inverse(translate * rotate);
    }

    glm::mat4 ViewMatrixOrbital() {
        glm::mat4 translate = glm::translate(glm::mat4(1.0f), localPosition);
        glm::mat4 aroundOnePoint = glm::translate(glm::mat4(1.0f), aroundPoint);
        glm::mat4 rotate = glm::mat4_cast(orientation);
        return glm::inverse(aroundOnePoint * rotate * translate);
    }

```

The first one is messed up when I **look directly from up to down** or **down to up**.

The second one, I can never go back to the **same position** when I just drag/draw a circle with my mouse...

I really need some help to make a human-friendly, "robust", and elegantly quaternion camera(some things like the camera in the Ace Combat or EVERSPACE)...

> The resources I have used:
>
> https://stackoverflow.com/questions/49609654/quaternion-based-first-person-view-camera
>
> http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/
>
> https://www.3dgep.com/understanding-the-view-matrix/
>
> and of course...
>
> https://www.youtube.com/watch?v=d4EgbgTm0Bg&ab\_channel=3Blue1Brown

Sorry for my English...

# Answer
OK, thanks for the links from DMGregory and the ideal form HolyBlackCat.

I think that I find a temporary solution.

Of course, it is not very elegant and not perfect... Any suggestions or comments are very welcome！

**new Update() function**

```
void Update(float delta) {

        glm::quat qYaw = glm::angleAxis(glm::radians(-yaw), up);
        glm::quat qPitch = glm::angleAxis(glm::radians(-pitch), right);
        glm::quat qRoll = glm::angleAxis(glm::radians(roll), front);

```

```
        orientation = glm::normalize(tempQuat * qRoll * qPitch * qYaw * orientation);

```

Here I add a **tempQuat** which is used for correcting the "roll".

```
        front = glm::normalize(orientation * glm::vec3(0, 0, -1.0f));
        up = glm::normalize(orientation * glm::vec3(0, 1.0f, 0));
        right = glm::normalize(orientation * glm::vec3(1.0f, 0, 0));

```

```
        auto ClosestAxis = [](glm::vec3 v) {...};

```

**ClosestAxis** is a helper function that is used to find the closest axis(like (0,1,0), actually I add all the axes and all the vectors between those axes).

```
        glm::vec3 UpNormal = glm::normalize(glm::cross(front, ClosestAxis(up)));
        glm::vec3 targetUp = glm::normalize(glm::cross(UpNormal, glm::cross(up, UpNormal)));
        if (!roll)
        {
            glm::quat q = glm::rotation(up, targetUp);
            tempQuat = glm::slerp(glm::identity<glm::quat>(), q, delta * 2.0f);
        }

```

The first cross-product gets **a normal fo a plane**, the "human-friendly intuitive vertical plane".

The Next double cross-product comes from the ideal: How can you make a projection of a vector onto a plane?. It projects the **up** to the "human-friendly intuitive vertical plane".

Now we can get a rotation quaternion between **up** and **targetUp**(the projected one), and we slerp them. I arbitrarily give a speed (**delta\*2.0f**) of "correcting roll".

Because Update() will be executed every frame(actually, this function does something like infinitely close to targetUp), **it can be anything smaller than 1.0**(it may feel uncomfortable without a delta-time, like a plain number 0.01f ).

Other codes remain the same.

```

        fps = ViewMatrix();
        tps = ViewMatrixOrbital();

                //Clear Everything
        yaw = 0;
        pitch = 0;
        roll = 0;
    }

```

**the ClosestAxis lambda helping function**

```
auto ClosestAxis = [](glm::vec3 v) {
            auto axis = std::max
            (
                {
                  glm::normalize(glm::vec3(1.0f,1.0f,0)),glm::normalize(glm::vec3(1.0f,-1.0f,0)),
                  glm::normalize(glm::vec3(-1.0f,1.0f,0)),glm::normalize(glm::vec3(-1.0f,-1.0f,0)),
                  glm::normalize(glm::vec3(1.0f,0,1.0f)),glm::normalize(glm::vec3(1.0f,0,-1.0f)),
                  glm::normalize(glm::vec3(-1.0f,0,1.0f)),glm::normalize(glm::vec3(-1.0f,0,-1.0f)),
                  glm::normalize(glm::vec3(0,1.0f,1.0f)),glm::normalize(glm::vec3(0,1.0f,-1.0f)),
                  glm::normalize(glm::vec3(0,-1.0f,1.0f)),glm::normalize(glm::vec3(0,-1.0f,-1.0f)),
                  glm::vec3{0, 0, 1.0f},glm::vec3{0, 0, -1.0f},
                  glm::vec3{1.0f, 0, 0},glm::vec3{-1.0f, 0, 0},
                  glm::vec3{0,1.0f, 0},glm::vec3{0, -1.0f, 0},
                  glm::normalize(glm::vec3(1.0f,1.0f,1.0f)),glm::normalize(glm::vec3(-1.0f,1.0f,1.0f)),
                  glm::normalize(glm::vec3(1.0f,1.0f,-1.0f)),glm::normalize(glm::vec3(-1.0f,1.0f,-1.0f)),
                  glm::normalize(glm::vec3(1.0f,-1.0f,1.0f)),glm::normalize(glm::vec3(-1.0f,-1.0f,1.0f)),
                  glm::normalize(glm::vec3(1.0f,-1.0f,-1.0f)),glm::normalize(glm::vec3(-1.0f,-1.0f,-1.0f)),
                },
                [&](glm::vec3 v1, glm::vec3 v2) {return glm::dot(v, v1) < glm::dot(v, v2); }
            );
            return axis;
        };

```
> 2 votes

---
Tags: opengl, camera, quaternion, glm
---


# Question
Title: Technical differences between square and hexagon for a grid?
I'm developing a 2D city-building game and trying to decide on the type of grid. There will be vehicles, so the unit movement is important too.

I know there are visual differences for using Squares or Hexagons, what I want know is:

* What are the issues for programming each type of grid regarding implementation and performance?
* Is there a tradeoff or specific benefit for using one of them in a game context?

# Answer
> 7 votes
I'd consider a `Square-based` grid as a "base" type of tiles in any game. Such grid is simple to imagine and moves over this grid are simple to understand. It's also very simple to implement "under the hood". Those are few reasons why even the Chess game uses it :). Additionally, this grid helps you make "regular" levels, because `Vertical` and `Horizontal` are natural directions here. So if you make, let's say a SimCity clone it's very easy to have perpendicular roads.

The biggest disadvantage of `Square-based` grids is that they doesn't keep distances very well, because when you move by one tile in `N/W/E/S` directions you basically move by one tile size, but when you move in directions like `NW/ES/...` then you'll move by `sqrt(2)*tileSize`. It's not so big problem in computer games but it was a big flaw in `strategy/tactical` board games.

Because of this problem people tried to find some other way to divide 2D space, so the movements between tiles would be more similar to the real movement. It happens that the only possible way, better than squares is to use `Hexagons`.

`Hexagon-based` grids are much better for strategy-like games because movements are more natural, but they are much harder to implement. They have also 3 main directions, where one of them may be `Horizontal` OR `Vertical` but not both! So try to imagine a city with perpendicular roads built on a such grid...

Personally, for a game like `SimCity` I wouldn't think much and used `Squares`. In fact, I'd use squares in every game that is not a turn-based tactical game. But depending on your taste you need to choose your own. Maybe you'll want to make a one-of-its-kind, `Hex-based SimCity` clone :) ?

# Answer
> 5 votes
Can't comment yet, so I'll give answer short answer.

From my experience, square tiles are a little simpler to implement. If you are using e.g. a two-dimensional array, tile position is array index multiplied with tile size (at least that's what it boils down to). Finding neighboring tiles is as simple as adding one to the index (and maybe wrapping the value to not go outside of the map).

Hexagonal tiles however have more neighbors and require a little more work to position correctly. Nothing complex though, just a few multiplications usually. What you will need to look out for is that every other row/column has one less tile than the others, since their edges don't line up.

Bottom line: Both aren't too difficult, just choose what is right for your game design.

One last thing to look out for with hexagons in your specific case may be something like roads, and when a straight road leads out of a tile at its pointy end, how do you implement that? Is it connected to the tile it does not share a border (only a corner) with? Do the tiles touching that corner need to know about the road? However, questions like that exist for squares as well (e.g. diagonal road). The answer to your overarching question is probably something only you can arrive at, depending on what you plan to do.

# Answer
> 2 votes
For a city-building game, I'd definitely use a square grid, for one simple reason: many real-world cities are built on a square grid plan, while very few if any are built using a hexagonal grid.

The main disadvantage of square grids is that, if you allow diagonal movement, a single diagonal step covers a bit (about 1.414 times) more distance than an orthogonal step. The solution to this issue is to make diagonal movement slightly slower to compensate; if you're also measuring time in discrete ticks, having an orthogonal step tack two ticks and a diagonal step take three ticks gives a pretty good approximation to realistic movement.

The other option would be to go "gridless", allowing the player to place roads and buildings at (more or less) arbitrary positions and angles. This could be implemented by having a very fine underlying grid (say, 0.1 to 1 meters per grid step), allowing roads to drawn in a straight (or curved) line between any two grid points, and allowing buildings to be placed at arbitrary positions and angles. Of course, this makes overlap and proximity checking a bit more complicated, but it's not that hard to implement.

To make things easier for the player, you'll probably want to snap road endpoints to existing roads and building entrances, and snap building positions and orientations to nearby roads. (In particular, if I try to move a planned building *on top of* a road, the game should position it along the road instead.) You may also want to give the player the option to snap roads and building to a secondary, coarser grid (possibly with a customizable grid spacing) to make it easier to keep things tidy. Depending on how fancy you want to get, you could even let the player rotate the grid or set up multiple grids and custom guide lines.

In any case, using a gridless (fine grid) design and a fine time step gets rid of any issues with diagonal movement: instead of counting ticks to move one grid step in some direction, you just measure the distance along the road from point A to point B (using the Pythagorean theorem) and make the time proportional to that; the fine grid and time step make any roundoff errors negligible.

# Answer
> 0 votes
I would suggest using a "stagger grid", in which every row is displaced half a square west of the one to its north \[somewhat like the keys on a typical keyboard\]. From a programming perspective, a stagger grid can be processed much like a square grid except that movement will be permitted NW and SE, but not NE and SW, and a map whose sides run north-south will to the program appear as a "diamond" shape. A stagger grid can easily be rendered to look like a hex grid (just scale the X and Y axes suitably and superimpose hexagons on it) and doesn't require any really weird programming.

# Answer
> 0 votes
I recommend Amit Patel's extensive writing on the subject of grids in games. I recommend that you start here, and then if you like his expository style, read more here.

If you still have *specific* questions, then come back and ask them here.

# Answer
> 0 votes
One tradeoff for using hexagon in a game context is in strategy games: the number of sides could cause inbalance in strategy games (say Fire Emblem).

In this example, everyone from enemy's side can act at in one go. Your character has to defend at maximum from 4 sides and survive a round. Now if it is hexagon, then there will be additional sides of attack.

Therefore, for hexagon boards, either the attack point/health point ratio is lower, or the design would not allow every unit from one side to act at once, but instead have a system which shuffles next active unit.

---
Tags: 2d, software-engineering, tiles, hexagonal-grid
---


# Question
Title: Invisible sprites with requestAnimationFrame
I'm trying to animate a sprite sheet. I have a single image, and multiple objects of the same type but drawn at different locations on the canvas.

What I'm trying to do is have each object move with an animation speed of its own, and an overall game framerate using `requestAnimationFrame`.

Be I find that it clears the whole canvas, instead of redrawing.
I've previously tried the `setInterval` approach, but it causes flickering (I can't really tell why, even after googling it).

const objectsArray = []
const gameFrameRate = 1000/30;
let allowedSoldiersQuantity = 30;
let globalImageObjects = [];

let newObject = new genericObject('robot.png', 200, 200);
objectsArray.push(newObject)
let otherObject = new genericObject('2.png', 300, 300);
objectsArray.push(otherObject)

canvas = document.getElementById('game_canvas');
context = canvas.getContext('2d');
canvas.width = 1200;
canvas.height = 720;
canvas.style.borderColor = 'red'
canvas.style.borderWidth = '5px'

setup = function() {

    // setInterval Approach
    //setInterval(function (){
    //    context.clearRect(0, 0, canvas.width, canvas.height)
    //    objectsArray.map((element) => {
    //        element.animateObjectImage(element.objectImage, 4)
    //    })
    //},30)

    // RequestAnimationFrame approach
    objectsArray.map((element) => {
        element.animateObjectImage(element.objectImage, 9)
    })
    context.clearRect(0, 0, canvas.width, canvas.height)
    window.requestAnimationFrame(setup)
}
window.requestAnimationFrame(setup)

document.addEventListener('click', (event) => {
    console.log(event.x);
    console.log(event.y);
    if (allowedSoldiersQuantity){
        let object = new genericObject('robot.png', event.x, event.y)
        objectsArray.push(object)
        object.animateObjectImage(object.objectImage, 5)
        allowedSoldiersQuantity -= 1;
    }
}, false)

function genericObject(objectSpriteSheet, xPosition, yPosition){
    this.objectImage = (function (){
        let newImageObject = new Image()
        newImageObject.src = objectSpriteSheet
        return (newImageObject)
    })()
    this.animateObjectImage = function(objectImage, frameRate){
        let setIntervalTime = 1000 / frameRate;
        let currentFrame = 1;
        let totalSprites = 8;
        let spriteHeight = objectImage.height;
        let spriteWidth = objectImage.width / totalSprites;
        setInterval(function animateObjectSprites(){
            currentFrame = (currentFrame + 1) % totalSprites;
            let screenX = currentFrame * spriteWidth;
            context.drawImage(objectImage, screenX, 0, spriteWidth, spriteHeight, xPosition, yPosition, spriteWidth, spriteHeight);
            currentFrame++;
        }, setIntervalTime)
    }
}
//setup(); // This function should be run with the setInterval approach
```
</code></pre>

# Answer
> 0 votes
The point of a function passed to `requestAnimationFrame` which then passes itself back to `requestAnimationFrame` at its end is not to be a setup-function. It's a drawing-function which gets called over and over again by the browser's rendering engine.

I think what it is supposed to do in your code example is to prepare the canvas for first rendering and schedule the animations for all the objects by calling their `animateObjectImage` functions which then all create an interval. This is something you only need to do **once**, not over and over again. And you don't need to call it via `requestAnimationFrame`. So both instances of the line `window.requestAnimationFrame(setup)` make no sense. Just call the setup method once when you start the game.

Then there is the problem that you have your calls to `context.drawImage` not during the `requestAnimationFrame` function but as part of the `setInterval` function. That's not how you are supposed to do it! All drawing **should** happen during `requestAnimationFrame`, so the web browser can properly integrate the rendering into its own rendering loop. Functions scheduled via `setInterval` get executed whenever, so they **should not** contain any canvas drawing.

Now you might wonder: "But I don't know how often the browser calls requestAnimationFrame. How am I supposed to properly time my animations with that function?"

The answer is to separate logic from drawing! A principle that should be obeyed in any well-designed game architecture.

* Have the setInterval function set which frame is the currently displayed frame for that object.
* Have the requestAnimationFrame draw whatever is the currently displayed frame for the object.

You can do that by breaking the `animateObjectImage` method of your `genericObject` function pseudo-class into two separate methods `setup` and `draw`. The setup method does initialization and schedules the logic (but not the drawing!) and the draw method draws whatever state the logic has set.

```
function genericObject(objectSpriteSheet, xPosition, yPosition){
    this.objectImage = (function (){
        let newImageObject = new Image()
        newImageObject.src = objectSpriteSheet
        return (newImageObject)
    })()
    // setup function
    this.setup = function(objectImage, frameRate){
        let setIntervalTime = 1000 / frameRate;
        let currentFrame = 1;
        let totalSprites = 8;
        let spriteHeight = objectImage.height;
        let spriteWidth = objectImage.width / totalSprites;
        setInterval(function(){
            currentFrame = (currentFrame + 1) % totalSprites;
            currentFrame++;
        }, setIntervalTime)
    }
    // draw function
    this.draw = function() {
            let screenX = currentFrame * spriteWidth;
            context.drawImage(objectImage, screenX, 0, spriteWidth, spriteHeight, xPosition, yPosition, spriteWidth, spriteHeight);
    }
}

```

Then in the main program, you have both a setup method and a draw method. The setup method starts the animation loop of the draw method:

```
function setup() {
    objectsArray.forEach((element) => {
        element.setup(element.objectImage, 9)
    })
    window.requestAnimationFrame(draw)
}

function draw() {
    context.clearRect(0, 0, canvas.width, canvas.height)
    objectsArray.forEach((element) => {
        element.draw()
    })
    window.requestAnimationFrame(draw)
}

```

And then you initialize your game by calling the setup method when the page has loaded:

```
window.onload = function(){
    /* ...all the other initializations... */
    setup();
}

```

By the way, there is another problem here that you don't wait with drawing until all the sprites have loaded. But that's another problem for another question.

---
Tags: javascript, html5, html-canvas, spritesheet
---


# Question
Title: When implementing pressing Enter to restart the game, should I use Keyboard::IsKeyPressed or use Event::KeyReleased in some way?
When implementing pressing Enter to restart the game, should I use Keyboard::IsKeyPressed or use Event::KeyReleased in some way? I am afraid that Keyboard::IsKeyPressed will restart the game in excess of hundred times.Because a briefest of pressed will last a significant fraction of second.

# Answer
sf::Event::KeyPressed & sf::Event::KeyReleased are events triggerd when that thing is done. Where as isKeyPressed is a function that tells you if a key is pressed right now in that iteration of the window loop.

In general Events are used to do single things at a time. Everything else is usedd in each iteration. Any event trigger triggers a single event even if that event is ongoing throughout many iterations of the game loop.

A good example of usage of these two is character movement onscreen. Moving a character with an event event::Keypressed(Left) will act like a keyPress during writing text. Try holding down any letter on your keyboard in like a notepad. You'll see your single letter pop up once and then after delay multiple letters follow slowly.

With isKeypressed you have a sudden trigger thats continous until unfulfilled. For character movement isKeyPressed is the one to use.

For example button usage onscreen would be better done in events as you can hold that button down and only want a single click on it. event::Keypressed would be better then.

Also i recommend adding the event::Keypressed with another statement saying which key was pressed: event.type == sf::event::keyPressed && sf::keyboard::is::keypressed(LeftP) The above is used inside the event loop

you shouldnt use events outside the event loop. it would be pointless

For simple single key stroke usage use event key pressed or released. If you want to be fancy with eg a enter hold down for z seconds then iskepressed. It all boils down to like i said earlier, does it have to be continuous or can it be a single togglelike event
> 1 votes

---
Tags: sfml
---


# Question
Title: Texture does not draw with ATI Radeon RX, but does with NVIDIA/no GPU
I am getting a problem when trying to draw a texture on the following hardware (configuration 1):

*ATi Radeon RX 6600 XT*

Screen (OS Windows 11):

I have other hardware (configuration 2):

*nVidia Geforce GTX950M*

And it has no problems. Screen (OS Windows 10):

My code (I made a minimal example):

```
#include <Windows.h>

#include "Resource.h"

#include <d3d9.h>
#include <d3dx9math.h>
#include <dxerr9.h>

#include "stb_image.h"
#include <cassert>
#include <fstream>
#include <vector>

typedef intptr_t HTEXTURE;

struct vertex
{
    vertex() {}
    vertex(float x, float y, float z, DWORD col, float tx, float ty, float tx2, float ty2) :x(x), y(y), z(z), col(col), tx(tx), ty(ty),
        tx2(tx2), ty2(ty2) {}
    float           x, y;
    float           z;
    DWORD           col;
    float           tx, ty;
    float           tx2, ty2;
};

struct Quad
{
    vertex      v[4];
    HTEXTURE        tex;
    int             blend;
};

#define D3DFVF_HGEVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 | D3DFVF_TEX2)
#define D3DFVF_HGE_MASKEDVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 | D3DFVF_TEX2)
#define VERTEX_BUFFER_SIZE 4000
#define BLEND_COLORMUL      0
#define BLEND_ALPHABLEND    2
#define BLEND_NOZWRITE      0
#define BLEND_DEFAULT       (BLEND_COLORMUL | BLEND_ALPHABLEND | BLEND_NOZWRITE)

HINSTANCE hInst;
WCHAR szTitle[] = L"test";
WCHAR szWindowClass[] = L"test_win";
HWND hWnd;
IDirect3D9* pD3D;
IDirect3DDevice9* pD3DDevice;
D3DPRESENT_PARAMETERS* d3dpp;
D3DPRESENT_PARAMETERS                       d3dppW;
D3DPRESENT_PARAMETERS                       d3dppFS;
int                                         nScreenBPP;
D3DXMATRIX                                  matProj;
D3DXMATRIX                                  matView;
vertex* VertArray;
IDirect3DVertexBuffer9* pVB;
IDirect3DIndexBuffer9* pIB;
int                                         nPrim = 0;
D3DVIEWPORT9                                rCurrentViewPort;
RECT                    rectW;
LONG                    styleW;
Quad quad;
IDirect3DTexture9* pD3DXTex = 0;

BOOL                InitWin(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);

int _format_id(D3DFORMAT fmt)
{
    switch (fmt)
    {
    case D3DFMT_R5G6B5:     return 1;
    case D3DFMT_X1R5G5B5:   return 2;
    case D3DFMT_A1R5G5B5:   return 3;
    case D3DFMT_X8R8G8B8:   return 4;
    case D3DFMT_A8R8G8B8:   return 5;
    default:                return 0;
    }
}

void _SetProjectionMatrix(int width, int height)
{
    D3DXMATRIX tmp;
    D3DXMatrixScaling(&matProj, 1.0f, -1.0f, 1.0f);
    D3DXMatrixTranslation(&tmp, -0.5f, height + 0.5f, 0.0f);
    D3DXMatrixMultiply(&matProj, &matProj, &tmp);
    D3DXMatrixOrthoOffCenterLH(&tmp, 0.f, (float)width, 0, (float)height, 0.0f, 1.0f);
    D3DXMatrixMultiply(&matProj, &matProj, &tmp);
}

bool initD3d()
{
    static const char* szFormats[] = { "UNKNOWN", "R5G6B5", "X1R5G5B5", "A1R5G5B5", "X8R8G8B8", "A8R8G8B8" };
    D3DDISPLAYMODE          Mode;
    D3DFORMAT               Format = D3DFMT_UNKNOWN;
    UINT nModes, i;

    pD3D = Direct3DCreate9(D3D_SDK_VERSION);

    pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &Mode);

    ZeroMemory(&d3dppW, sizeof(d3dppW));

    d3dppW.BackBufferWidth = 1366;
    d3dppW.BackBufferHeight = 768;
    d3dppW.BackBufferFormat = Mode.Format;
    d3dppW.BackBufferCount = 1;
    d3dppW.MultiSampleType = D3DMULTISAMPLE_NONE;
    d3dppW.hDeviceWindow = hWnd;
    d3dppW.Windowed = TRUE;

    d3dppW.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dppW.PresentationInterval = D3DPRESENT_INTERVAL_ONE;

    nModes = pD3D->GetAdapterModeCount(D3DADAPTER_DEFAULT, Mode.Format);

    int nFullscreenWidth = GetSystemMetrics(SM_CXSCREEN);
    int nFullscreenHeight = GetSystemMetrics(SM_CYSCREEN);

    for (i = 0; i < nModes; ++i)
    {
        pD3D->EnumAdapterModes(D3DADAPTER_DEFAULT, Mode.Format, i, &Mode);

        if (Mode.Width != (UINT)nFullscreenWidth || Mode.Height != (UINT)nFullscreenHeight)
            continue;

        if (nScreenBPP == 16 && (_format_id(Mode.Format) > _format_id(D3DFMT_A1R5G5B5)))
            continue;

        if (_format_id(Mode.Format) > _format_id(Format))
            Format = Mode.Format;
    }

    if (Format == D3DFMT_UNKNOWN)
    {
        return false;
    }

    ZeroMemory(&d3dppFS, sizeof(d3dppFS));

    d3dppFS.BackBufferWidth = 1366;
    d3dppFS.BackBufferHeight = 768;
    d3dppFS.BackBufferFormat = Mode.Format;
    d3dppFS.BackBufferCount = 1;
    d3dppFS.MultiSampleType = D3DMULTISAMPLE_NONE;
    d3dppFS.hDeviceWindow = hWnd;
    d3dppFS.Windowed = TRUE;
    d3dppFS.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dppFS.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;

    d3dppFS.PresentationInterval = D3DPRESENT_INTERVAL_ONE;

    d3dpp = true ? &d3dppW : &d3dppFS;

    if (_format_id(d3dpp->BackBufferFormat) < 4)
        nScreenBPP = 16;
    else
        nScreenBPP = 32;

    // Create D3D Device
    UINT       nAdapter = D3DADAPTER_DEFAULT;
    D3DDEVTYPE eDeviceType = D3DDEVTYPE_HAL;

    D3DCAPS9 caps;
    pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);

    DWORD dwVP;
    if ((caps.VertexShaderVersion < D3DVS_VERSION(1, 1)) || !(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT))
    {
        dwVP = D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED;
    }
    else
    {
        dwVP = D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED;
    }

    dwVP = D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED;

    pD3D->CreateDevice(nAdapter, eDeviceType, hWnd, dwVP, d3dpp, &pD3DDevice);

    _SetProjectionMatrix(1366, 768);
    D3DXMatrixIdentity(&matView);

    return true;
}

IDirect3DTexture9* loadTexture(IDirect3DTexture9* texture, const std::string& path)
{
    if (!pD3DDevice)
        return nullptr;

    bool bResult = false;

    DWORD               dwSizeFile = 0;
    D3DFORMAT           fmt1;
    D3DFORMAT           fmt2;

    std::ifstream file(path, std::ios::binary | std::ios::ate);
    dwSizeFile = file.tellg();
    file.seekg(0, std::ios::beg);
    std::vector<char> pDataTex(dwSizeFile);
    if (!file.read(pDataTex.data(), dwSizeFile))
        return nullptr;

    fmt1 = D3DFMT_A8R8G8B8;
    fmt2 = D3DFMT_UNKNOWN;

    int nWidth, nHeight, nBPP;
    int nRet = stbi_info_from_memory((stbi_uc*)pDataTex.data(), dwSizeFile, &nWidth, &nHeight, &nBPP);

    HRESULT hr = D3DXCreateTextureFromFileInMemoryEx(pD3DDevice, pDataTex.data(), dwSizeFile,
        D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2,
        0,  // Mip levels
        0,                              // Usage
        fmt1,                           // Format
        D3DPOOL_MANAGED,                // Memory pool
        D3DX_FILTER_NONE,               // Filter
        D3DX_DEFAULT,                   // Mip filter
        0,                              // Color key
        NULL, NULL, &texture);

    return texture;
}

bool initQuad()
{
    quad.v[0] = vertex(0, 0, 1, -1, 0, 0, 0, 0);
    quad.v[1] = vertex(1100, 0, 1, -1, 1, 0, 0, 0);
    quad.v[2] = vertex(1100, 650, 1, -1, 1, 1, 0, 0);
    quad.v[3] = vertex(0, 650, 1, -1, 0, 1, 0, 0);
    quad.tex = -1;
    quad.blend = 2;

    return true;
}

bool initGeometry()
{
    VertArray = 0;

    pD3DDevice->CreateVertexBuffer(VERTEX_BUFFER_SIZE * sizeof(vertex), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_HGEVERTEX, D3DPOOL_DEFAULT, &pVB, NULL);

    pD3DDevice->SetVertexShader(NULL);
    pD3DDevice->SetFVF(D3DFVF_HGEVERTEX);
    pD3DDevice->SetStreamSource(0, pVB, 0, sizeof(vertex));

    pD3DDevice->CreateIndexBuffer(VERTEX_BUFFER_SIZE * 6 / 4 * sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &pIB, NULL);

    WORD* pIndices, n = 0;
    if (FAILED(pIB->Lock(0, 0, (void**)&pIndices, 0)))
    {
        return false;
    }

    for (int i = 0; i < VERTEX_BUFFER_SIZE / 4; i++)
    {
        *pIndices++ = n;
        *pIndices++ = n + 1;
        *pIndices++ = n + 2;
        *pIndices++ = n + 2;
        *pIndices++ = n + 3;
        *pIndices++ = n;
        n += 4;
    }

    pIB->Unlock();
    pD3DDevice->SetIndices(pIB);

    pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
    pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);

    pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
    pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
    pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

    pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
    pD3DDevice->SetRenderState(D3DRS_ALPHAREF, 0x01);
    pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);

    pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
    pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
    pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
    pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
    pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
    pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);

    pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
    pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
    pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_MODULATE); // TODO: problem
    pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
    pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
    pD3DDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);

    pD3DDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);

    pD3DDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
    pD3DDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);

    pD3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
    pD3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
    pD3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP);

    pD3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);
    pD3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER);
    pD3DDevice->SetSamplerState(1, D3DSAMP_BORDERCOLOR, D3DCOLOR_ARGB(0x0, 0, 0, 0));

    pD3DDevice->SetTransform(D3DTS_VIEW, &matView);
    pD3DDevice->SetTransform(D3DTS_PROJECTION, &matProj);

    D3DVIEWPORT9 vp;
    HRESULT hr = pD3DDevice->GetViewport(&vp);
    if (hr == D3D_OK)
        rCurrentViewPort = vp;

    pD3DXTex = loadTexture(pD3DXTex, "Tiger-PNG-Image.png");
    initQuad();

    return true;
}

void SetTexture()
{
    pD3DDevice->SetTexture(0, pD3DXTex);
}

bool beginScene()
{
    pD3DDevice->BeginScene();
    pVB->Lock(0, 0, (VOID**)&VertArray, D3DLOCK_DISCARD);
    return true;
}

void endScene()
{
    pVB->Unlock();
    VertArray = 0;
    nPrim = 0;
    pD3DDevice->EndScene();

    pD3DDevice->Present(NULL, NULL, NULL, NULL);
}

void clearScene()
{
    int color = D3DCOLOR_ARGB(255, 0, 125, 0);
    pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, color, 1.0f, 0);
}

void renderQuad(Quad* quad)
{
    SetTexture();
    memcpy(&VertArray[nPrim * 4], quad->v, sizeof(vertex) * 4);
    nPrim++;
    pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, nPrim << 2, 0, nPrim << 1);
}

void _UpdateRects()
{
    int width = 1366;
    int height = 768;

    rectW.left = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
    rectW.top = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
    rectW.right = rectW.left + width;
    rectW.bottom = rectW.top + height;
    styleW = WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE;
    AdjustWindowRect(&rectW, styleW, FALSE);

}

BOOL InitWin(HINSTANCE hInstance, int nCmdShow)
{
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TESTRXBUG));
    wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = szWindowClass;
    wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    RegisterClassExW(&wcex);

    _UpdateRects();
    hWnd = CreateWindowEx(0, szWindowClass, szTitle, styleW,
        rectW.left, rectW.top, rectW.right - rectW.left, rectW.bottom - rectW.top,
        NULL, NULL, hInstance, NULL);

    if (!hWnd)
        return FALSE;

    ShowWindow(hWnd, nCmdShow);

    return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
    _In_opt_ HINSTANCE hPrevInstance,
    _In_ LPWSTR    lpCmdLine,
    _In_ int       nCmdShow)
{
    if (!InitWin(hInstance, nCmdShow))
        return FALSE;

    MSG msg = { 0 };

    initD3d();
    initGeometry();

    while (msg.message != WM_QUIT)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
        {
            if (GetMessage(&msg, NULL, 0, 0))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
        else
        {
            clearScene();
            beginScene();
            renderQuad(&quad);
            endScene();
        }
    }

    return (int)msg.wParam;
}

```

The problem is on this line:

```
pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_MODULATE); // TODO: problem

```

Also, if I set another texture for rendering at index 1, then everything will work (not correctly, but the rendering will work):

```
pD3DDevice->SetTexture(0, pD3DXTex);
pD3DDevice->SetTexture(1, pD3DXTex); // this

```

How to fix it?

P.S.: I tested on a Windows 11 virtual machine with configuration 1, but without a video card - everything worked correctly.

# Answer
> 3 votes
I can see that you're checking the HRESULTs returned from D3D functions in some cases (but not all of them), and where you're checking them you just silently handle the error. I'd suggest adding debug logging and/or assert()s for every D3D function call that returns an `HRESULT`.

Ideally you'd also enable the D3D9 debug runtime using the DirectX Control Panel, and see what errors get reported with it enabled. In my experience, if you're doing something that works on one GPU and fails on another, you're probably using the API in a way that's not quite correct, and one of the drivers is letting you get away with not using the API correctly. The debug runtimes will normally catch those errors. Unfortunately, you'll need Windows 7 / XP to use the debug runtimes. See https://stackoverflow.com/questions/73295505/how-to-enable-direct3d-9-debug-output-on-windows-10

However, D3D9 is so old now that I wouldn't recommend using it for anything, unless you really need to work with very old hardware / software. For anything else, I'd suggest starting with D3D11 instead. D3D11 has much better tools available to help you debug any problems you encounter.

---
Tags: textures, directx, directx9
---


# Question
Title: How to show orientation on an image minimap in Unity
Initial Question:

I'm trying to create a minimap for my game in Unity. It consists of a 2D image sprite within a mask. I've got the rotation and the movement within the mask down, but the only problem is the fact that the image rotates around its central point, instead of the central point of the mask, which is where the player is. Is there any way to fix this in code or using parenting or something? Any help is appreciated.

Code for the image:

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class UIMinimap : MonoBehaviour
{
    public Image minimap;
    public Transform border;

    private float xOffset;
    private float yOffset;

    // getting values from the player van
    public CarController van;
    private float yRotation;
    private Vector3 eulerRotation;
    private Quaternion rotation;
    private float yMovement;
    private float xMovement;
    public Vector3 Movement;

    void Start()
    {
        // getting offset which changes with screen size
        xOffset = transform.position.x;
        yOffset = transform.position.y;
    }

    void Update()
    {
        // Getting Y rotation of the van (direction facing)
        yRotation = van.vanRotation.eulerAngles.y;
        // turning that into a vector for rotation of plane (in Z as rotation of map is on a different plane to van)
        eulerRotation = new Vector3(0, 0, yRotation);
        // converting euler angles into quaternion
        rotation.eulerAngles = eulerRotation;
        transform.rotation = rotation ;

        // converting the position of the van on the real map to movement of the image, 0.247... is the scale of the image, while x and
        // y offset account for screensize
        yMovement= (-van.transform.position.x * (float)0.24721213) + (float) + yOffset;
        xMovement = (-van.transform.position.z * (float)0.24721213) + (float) + xOffset;
        Movement = new Vector3(xMovement, yMovement, 0);
        transform.position = Movement;
    }
}

```

# Answer
> 0 votes
The way I did this was to keep a marker in the centre of the minimap mask, and rotate the marker with the player. The movement of the minimap can just be moved with the scale of the map. Example:

Marker:

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UIMarker : MonoBehaviour
{
    public CarController van;
    public float yRotation;
    private Vector3 eulerRotation;
    private Quaternion rotation;

    // Update is called once per frame
    void Update()
    {
        // Getting Y rotation of the van (direction facing)
        yRotation = van.vanRotation.eulerAngles.y + 90;
        // turning that into a vector for rotation of plane (in Z as rotation of map is on a different plane to van)
        eulerRotation = new Vector3(0, 0, -yRotation);
        // converting euler angles into quaternion
        rotation.eulerAngles = eulerRotation;
        transform.rotation = rotation;
    }
}

```

Minimap:

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class UIMinimap : MonoBehaviour
{
    public CarController van;
    public float screenHeight;
    public float screenWidth;

    private float xOffset;
    private float yOffset;
    private float yMovement;
    private float xMovement;
    public float yScale;
    public float xScale;
    public Vector2 Movement;

    void Start()
    {
        // getting offset which changes with screen size
        xOffset = transform.position.x;
        yOffset = transform.position.y;
        // declaring the screen width and height
        screenHeight = Screen.height;
        screenWidth = Screen.width;
        // dividing the height/width of a screen by a factor that adjusts for the scale of the map
        yScale = screenHeight / 1675;
        xScale = screenWidth / 3350;
    }

    void FixedUpdate()
    {

        // converting the position of the van on the real map to movement of the image, movement is determined by the scale
        // of the minimap to the actual terrain, while x and y offset change with screen size so must be declared and added
        yMovement= (van.transform.position.x * yScale) + yOffset;
        xMovement = (-van.transform.position.z * xScale) + xOffset;
        Movement = new Vector2(xMovement, yMovement);
        transform.position = Movement;
    }
}

```

This is definitely not the most elegant solution, but works well enough for my purposes

---
Tags: unity, 2d, rotation, sprites, unity-ui
---


# Question
Title: Rendering large objects beyond far clipping plane
Is it possible to force rendering of an object that's beyond the far clipping plane? For example, more realistic "space" rendering, where a large mesh such as a planet should be rendered even beyond the far clipping plane.

As a software developer in another field (but with an interest in video games!) I have only a very basic understanding of rendering engines - so please excuse if any of my assumptions in this question are wrong:

In every game I've played that includes space, usually one can tell the "trick" they're using to render large objects such as planets, is to make them smaller and move them closer to the camera such that they're close enough as to not be beyond the far clipping plane. This works kind of well, but the illusion breaks if one moves the camera left and right, and can see that the "large object" is actually much closer than the texture would have you believe.

What are the drawbacks (or maybe it's just technically infeasible?) to simply making these large objects closer to real size, placing them well beyond the far clipping plane, and forcing the rendering engine to render them no matter what? I'm aware that this could be a good candidate for just being a skybox, but what if you wanted something more complex, like the object rotating, or moving around?

As a follow-up, I'm also curious if there are any rendering engines that are designed to accommodate something like this. Technical answers, links to papers, or just plain math on the subject is greatly appreciated!

# Answer
> 3 votes
The clipping planes are used to scale the depth buffer. If the range the buffer has to cover is too large, you get depth-fighting where meshes can't work out which one is closer to the camera.

The only methods I'm aware of to achieve the desired effect are:

* Do one render for distant objects, then another over the top of it for foreground.
* Cheat... Either use billboards that are scaled to appear appropriately sized when placed closer than the far clip plan or perhaps generate a skybox on-the-fly at low frequency. Depends on your use-case

Ultimately, \[excluding VR\] distance in computer graphics is a fairly arbitrary concept given there's no absolute scale.

Even with VR, very distant objects will appear identical between eyes.

---
Tags: 3d, rendering
---


# Question
Title: What's the most efficient way to find barycentric coordinates?
In my profiler, finding barycentric coordinates is apparently somewhat of a bottleneck. I am looking to make it more efficient.

It follows the method in shirley, where you compute the area of the triangles formed by embedding the point P inside the triangle.

Code:

```
Vector Triangle::getBarycentricCoordinatesAt( const Vector & P ) const
{
  Vector bary ;

  // The area of a triangle is
  real areaABC = DOT( normal, CROSS( (b - a), (c - a) )  ) ;
  real areaPBC = DOT( normal, CROSS( (b - P), (c - P) )  ) ;
  real areaPCA = DOT( normal, CROSS( (c - P), (a - P) )  ) ;

  bary.x = areaPBC / areaABC ; // alpha
  bary.y = areaPCA / areaABC ; // beta
  bary.z = 1.0f - bary.x - bary.y ; // gamma

  return bary ;
}

```

This method works, but I'm looking for a more efficient one!

# Answer
Transcribed from Christer Ericson's Real-Time Collision Detection (which, incidentally, is an excellent book):

```
// Compute barycentric coordinates (u, v, w) for
// point p with respect to triangle (a, b, c)
void Barycentric(Point p, Point a, Point b, Point c, float &u, float &v, float &w)
{
    Vector v0 = b - a, v1 = c - a, v2 = p - a;
    float d00 = Dot(v0, v0);
    float d01 = Dot(v0, v1);
    float d11 = Dot(v1, v1);
    float d20 = Dot(v2, v0);
    float d21 = Dot(v2, v1);
    float denom = d00 * d11 - d01 * d01;
    v = (d11 * d20 - d01 * d21) / denom;
    w = (d00 * d21 - d01 * d20) / denom;
    u = 1.0f - v - w;
}

```

This is effectively Cramer's rule for solving a linear system. You will not get much more efficient than this—if this is still a bottleneck (and it might be: it doesn't look like it's much different computation-wise than your current algorithm), you'll probably need to find some other place to gain a speedup.

Note that a decent number of values here are independent of *p*—they can be cached with the triangle if necessary.
> 78 votes

# Answer
The Cramer's rule should be the best way to solve it. I am not a graphic guy, but I was wondering why in the book Real-Time Collision Detection they doesn't do the following simpler thing:

```
// Compute barycentric coordinates (u, v, w) for
// point p with respect to triangle (a, b, c)
void Barycentric(Point p, Point a, Point b, Point c, float &u, float &v, float &w)
{
    Vector v0 = b - a, v1 = c - a, v2 = p - a;
    float den = v0.x * v1.y - v1.x * v0.y;
    v = (v2.x * v1.y - v1.x * v2.y) / den;
    w = (v0.x * v2.y - v2.x * v0.y) / den;
    u = 1.0f - v - w;
}

```

This directly solves the 2x2 linear system

```
v v0 + w v1 = v2

```

while the method from the book solves the system

```
(v v0 + w v1) dot v0 = v2 dot v0
(v v0 + w v1) dot v1 = v2 dot v1

```
> 20 votes

# Answer
Slightly faster: Precompute the denominator, and multiply instead of divide. Divisions are much more expensive than multiplications.

```
// Compute barycentric coordinates (u, v, w) for
// point p with respect to triangle (a, b, c)
void Barycentric(Point a, Point b, Point c, float &u, float &v, float &w)
{
    Vector v0 = b - a, v1 = c - a, v2 = p - a;
    float d00 = Dot(v0, v0);
    float d01 = Dot(v0, v1);
    float d11 = Dot(v1, v1);
    float d20 = Dot(v2, v0);
    float d21 = Dot(v2, v1);
    float invDenom = 1.0 / (d00 * d11 - d01 * d01);
    v = (d11 * d20 - d01 * d21) * invDenom;
    w = (d00 * d21 - d01 * d20) * invDenom;
    u = 1.0f - v - w;
}

```

In my implementation, however, I cached all of the independent variables. I pre-calc the following in the constructor:

```
Vector v0;
Vector v1;
float d00;
float d01;
float d11;
float invDenom;

```

So the final code looks like this:

```
// Compute barycentric coordinates (u, v, w) for
// point p with respect to triangle (a, b, c)
void Barycentric(Point a, Point b, Point c, float &u, float &v, float &w)
{
    Vector v2 = p - a;
    float d20 = Dot(v2, v0);
    float d21 = Dot(v2, v1);
    v = (d11 * d20 - d01 * d21) * invDenom;
    w = (d00 * d21 - d01 * d20) * invDenom;
    u = 1.0f - v - w;
}

```
> 15 votes

# Answer
I tried to copy @NielW's code to C++, but I didn't get correct results.

It was easier to read https://en.wikipedia.org/wiki/Barycentric\_coordinate\_system#Barycentric\_coordinates\_on\_triangles and calculate the lambda1/2/3 as given there (no vector functions needed).

If p(0..2) are the Points of the triangle with x/y/z:

Precalc for triangle:

```
double invDET = 1./((p(1).y-p(2).y) * (p(0).x-p(2).x) +
                   (p(2).x-p(1).x) * (p(0).y-p(2).y));

```

then the lambdas for a Point "point" are

```
double l1 = ((p(1).y-p(2).y) * (point.x-p(2).x) + (p(2).x-p(1).x) * (point.y-p(2).y)) * invDET;
double l2 = ((p(2).y-p(0).y) * (point.x-p(2).x) + (p(0).x-p(2).x) * (point.y-p(2).y)) * invDET;
double l3 = 1. - l1 - l2;

```
> 3 votes

# Answer
I would use the solution that John posted, but I would use the SSS 4.2 dot intrinsic and sse rcpss intrinsic forthe divide, assuming you are ok restricting yourself to Nehalem and newer processes and limited precision.

Alternatively you could compute several barycentric coordinates at once using sse or avx for a 4 or 8x speedup.
> 2 votes

# Answer
You can convert your 3D problem into a 2D problem by projecting one of the axis-aligned planes and use the method proposed by user5302. This will result in exactly the same barycentric coordinates as long as you make sure your triangle does not project into a line. Best is to project to the axis-aligned plane that is as close as possible to the orientation of your triagle. This avoid co-linearity problems and ensure maximum accuracy.

Secondly you can pre-compute the denominator and store it for each triangle. This saves computations afterwards.
> 1 votes

# Answer
For a given point N inside triangle A B C, you can get the barycentric weight of point C by dividing the area of subtriangle A B N by the total area of triangle A B C.
> 1 votes

# Answer
It may not be the fastest answer, but it's definitely one of the cleanest: You can convert to homogenous coordinates in order to use Cramer's rule cleanly for each barycentric coordinate. Please ignore the strange syntax, it is a custom preprocessor I wrote over OpenCL C.

```
VEC3 barycentric(VEC3 P, Triangle3f tri){

    VEC3 A = VEC3::diff(_VEC3(tri.A),P);
    VEC3 B = VEC3::diff(_VEC3(tri.B),P);
    VEC3 C = VEC3::diff(_VEC3(tri.C),P);

    float Ax = A.unwrap()..x;
    float Ay = A.unwrap()..y;
    float Az = A.unwrap()..z;

    float Bx = B.unwrap()..x;
    float By = B.unwrap()..y;
    float Bz = B.unwrap()..z;

    float Cx = C.unwrap()..x;
    float Cy = C.unwrap()..y;
    float Cz = C.unwrap()..z;

    float Px = 0.0;
    float Py = 0.0;
    float Pz = 0.0;

    MAT4 M = __MAT4(

        Ax,Bx,Cx,1,
        Ay,By,Cy,1,
        Az,Bz,Cz,1,
        1, 1, 1, 0

    );

    float d = MAT4::det(M).scalarUnwrap();

    if(fabs(d)<DET_EPSILON){
        return VEC3::zero();
    }

    MAT4 M1 = __MAT4(

        Px,Bx,Cx,1,
        Py,By,Cy,1,
        Pz,Bz,Cz,1,
        1, 1, 1, 0

    );

    MAT4 M2 = __MAT4(

        Ax,Px,Cx,1,
        Ay,Py,Cy,1,
        Az,Pz,Cz,1,
        1, 1, 1, 0

    );

    MAT4 M3 = __MAT4(

        Ax,Bx,Px,1,
        Ay,By,Py,1,
        Az,Bz,Pz,1,
        1, 1, 1, 0

    );

    return VEC3::fromcoords(
        MAT4::det(M1).scalarUnwrap() / d,
        MAT4::det(M2).scalarUnwrap() / d,
        MAT4::det(M3).scalarUnwrap() / d
    );

}

```
> 0 votes

---
Tags: barycentric-coordinates
---


# Question
Title: Sprite becomes blurry or jagged when camera zooms out
My game uses 2D sprites in a 3D environment, and I'm really struggling with my sprites' quality.

I have high resolution vector art with clean linework created for my sprite. I'm exporting it as a .PNG for Unity, but no matter what anti-aliasing, filter, or MipMap options I select, the quality is much worse in Unity when the camera is zoomed out. :(

The quality looks fine up close. Turning on MipMaps for the sprite does an 'OK' job at reducing the jaggedness, but I really hate how blurry and dull it makes it look...

My game is in 1920 x 1080 format and the character is designed similar to this Mario example (also from a 1920 x 1080 format). So, it "should" be possible to make it look this good:

I've tried reviewing as much information on this as I can, but I can't seem to find a solution. Any kind of guidance or resolution would mean the world to me. It's probably worth mentioning that I am using URP with anti-aliasing also on in the settings. If I want my characters quality to look as good as the Mario example above, what specifically do I need to do?

# Answer
First, make sure your sprite/texture **import format is set to RGBA 32-bit**. Any other import settings apply some compression algorithms to save video memory/loading time, at the cost of image quality. It's usually a good trade-off for natural-looking noisy textures, but for crisp vector art or pixel graphics, the compression artifacts can be quite noticeable.

Next, if you're using Unity URP with default settings, you may also want to **disable the FXAA anti-aliasing** setting on the camera. This antialias pass is a good choice for 3D scenes with a lot of geometry aliasing, but if you're using sprites that won't be a problem, and the FXAA algorithm can be a bit over-eager about blurring crisp edges it sees in sprites.

PayasoPrince and I connected over Discord to troubleshoot this issue, and in this case it turned out that the two points above were responsible for almost all of the quality impacts. Once we imported the sprite uncompressed and without post-process AA, the default mipmap generation and filtering was enough to get quite good quality - even pixel-perfect to the source when looking at the highest-resolution mip with the right camera settings.

I wrote the rest of this answer before thinking of compression or AA filters as a culprit, so it goes into the weeds of how to get full control over your mipmaps. That turned out to be overkill for this case, but I'll leave it up in case it's helpful to others - just make sure you try the quick wins above first before going all the way down this rabbit hole!

---

Some background on why this happens:

Without mipmaps, as you shrink your texture down, the tiny fringe of half-coloured texels giving you a nice anti-aliased border between two coloured regions shrinks to almost nothing. The chance that any particular pixel's texture sample lands right on that razor edge goes toward zero, and so most pixels end up looking up their texture from one side or the other, 100% the colour on the left or 100% the colour on the right, resulting in that harsh stairstep transition with no blending.

Auto-generated mipmaps help with this by pre-generating smaller versions of the asset that are pre-blended for fast lookups (and better cache coherency which is good for performance). But when they only have a raster image to go off of, they have to make guesses about the true continuous colour field they're supposed to be approximating. Usually they'll use a simple box filter or some slightly more sophisticated ways of averaging the colours already baked into your raster. That averaging can smear out your borders more than a true supersample of the source vector would, contributing to the slight fuzziness you see. Unity also offers a Kaiser filter which is somewhat sharper - that might be enough, depending on your images.

You can take full control of this process by making your own mipmaps directly from your vector source. Your vector editing software is able to apply supersampling to the ground truth continuous image to get a very high-quality downsample, which anything working from just the raster can only approximate.

So instead of exporting just a single high-res sprite, you can export a whole sequence, each half the size of the previous. You can combine these images into a mipmap chain in DDS texture format — there are plugins for Photoshop and other image tools to help with this, or you can use DirectX utilities to do it manually.

Importing this into Unity, it will use your mipmaps instead of guessing at its own with recursive filters. Then anytime your sprite is displayed at exactly one of the resolutions you exported, and aligned with the pixel grid of the screen, you'll get crisp edges just like your direct vector output - pixel for pixel exact. So for best quality, try to export your sprite at a resolution such that the typical sizes it appears in your game each closely match the resolution of one of the source images in the mip chain. You can even swap between different versions of the sprites for closeup and far shots, if the sizes you need don't align well with a power of 2 relationship.

But in-between those sizes you can still run into trouble. By default, using trilinear filtering, the GPU will average two nearby mip levels to estimate the right colour for each pixel at an in-between size. This can again introduce a little fuzziness, both from the averaging, and because one of those levels is too low-res/blurred for the size you're drawing at. You can force the filtering to bilinear / choose just the nearest mipmap to sample from, which will introduce a little upscaling fuzz when scaled up and a little aliasing when scaled down from the closest native size you saved — and a visible pop during scaling as it switches sources discretely. Or you can apply a mipmapping bias to shift the lookup a little more strongly toward the more detailed mip, trading a little extra aliasing for crispness, while keeping the transitions smooth and pop-free.
> 4 votes

---
Tags: unity, sprites, graphics, antialiasing, mipmaps
---


# Question
Title: Camera Jitters When Displacing and Rotating Smoothly
**DISCLAIMER:** I am using Unity 5.6.5f1 for this code, I honestly don't know if there would be API updates on later versions, though I don't think so.

I tried to make a simple Third Person Camera that displaces and rotates towards a given target, with the following key parameters:

* Following types for both displacement and rotation. Right now the enum is just { Instant, Smooth }.
* Axes to ignore for both displacement and rotation, all axes in an enum.
* Axes to invert for the orbiting functionality.
* 'Relative Following' for both displacement and rotation. If the flags are checked the displacement/rotation will be relative to the target's orientation ('target.rotation * displacement' and 'target.rotation * rotation' for displacement and rotation respectively).
* An offset vector, which is affected by the displacement relative following's flag. It is treated as a normalized vector at runtime.
* A scalar of the aforementioned offset. Which is basically de distance between the camera and the target.
* An offset vector as Euler for the rotation, it is equally affected by the rotation relative following's flag.
* Other attributes, such as 'displacementFollowDuration', 'maxDisplacementFollowSpeed', 'rotationFollowDuration', 'maxRotationFollowingSpeed', etc., are for the smooth following. The attributes not mentioned are either self-explanatory or irrelevant (at least that's what I want to think, correct me if I may be wrong).

**The Problem:**

When the smooth flags are enabled for both displacement and rotation, the camera starts to shake, I think it has something to do with the rotation.

**Things I've tried already:**

* Call the rotation and displacement following on different threads (being Update, Late Update and FixedUpdate), not yet on coroutines. This time I made an enum 'LoopType' to encapsulate all threads, and avoid re-compiling each time I move the functions.
* Use different kinds of time deltas. By the same fashion of the threads, I made an enum 'TimeDelta' which encapsulates the 3 types of time deltas Unity offers.
* Change the smooth functions for both displacement and rotation, such as Lerp, SmoothDamp, Slerp, even custom elastic functions, etc.
* Sacrifing 1 frame by following the target's point of the last frame, as proposed here.
* Given that the target's displacement is that of a Rigidbody, this post suggests to attach a Rigidbody to the camera and displace/rotate it by Rigidbody.position/Rigidbody.rotation respectively.

**Camera's Script:**

```
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

[Flags]
public enum Axes
{
    None = 0,
    X = 1,
    Y = 2,
    Z = 4,

    XAndY = X | Y,
    XAndZ = X | Z,
    YAndZ = Y | Z,
    All = X | Y | Z
}

public enum LoopType { Update, LateUpdate, FixedUpdate }

public enum TimeDelta { Default, Fixed, Smooth }

public enum FollowingType { Instant, Smooth }

/// \TODO Maybe something like Lucky Tale and Resident Evil 4 and 5 camera (return to the original rotation if there are no axes)
public class GameplayCamera : MonoBehaviour
{
    public Transform target;                        /// Camera's Target.
    [Space(5f)]
    [Header("Displacement Following's Attributes:")]
    public LoopType followDisplacementAt;           /// Loop to do the Displacement Following.
    public FollowingType displacementFollowType;    /// Type of Following for Displacement.
    public TimeDelta displacementTimeDelta;         /// Displacement's Time Delta.
    public Axes ignoreDisplacementAxes;             /// Displacement Axes to Ignore.
    public Axes invertAxes;                         /// Axes to Invert.
    public Axes limitOrbitAxes;                     /// Orbit's Axes to Limit.
    public bool relativeDisplacementFollow;         /// Follow Target's Displacement Relative to Target's Orientation?.
    public bool limitDisplacementFollow;            /// Limit Displacement Following's Speed?.
    public Vector3 displacementOffset;              /// [Normalized] Displacement Offset between Camera and Target.
    public Vector2 orbitSpeed;                      /// Orbit's Speed on each Axis.
    public Vector2 minOrbitLimits;                  /// Orbit's Negative Boundaries.
    public Vector2 maxOrbitLimits;                  /// Orbit's Positive Boundaries.
    public float displacementFollowDuration;        /// Displacement's Follow Duration.
    public float maxDisplacementFolowSpeed;         /// Maximum Displacement's Follow Duration.
    public float minDistance;                       /// Minimum Distance Between Camera and Target.
    public float maxDistance;                       /// Maximum Distance Between Camera and Target.
    [Space(5f)]
    [Header("Rotation Following's Attributes:")]
    public LoopType followRotationAt;               /// Loop to do the Rotation Following.
    public FollowingType rotationFollowType;        /// Type of Following for Rotation.
    public TimeDelta rotationTimeDelta;             /// Rotations' Time Delta.
    public Axes ignoreRotationAxes;                 /// Rotation Axes to Ignore.
    public bool relativeRotationFollow;             /// Follow Target's Rotation Relative to Target's Orientation?.
    public bool limitRotationFollow;                /// Limit Rotation Following's Speed?.
    public Vector3 eulerRotationOffset;             /// Rotation Offset between Camera and Target as Euler.
    public float rotationFollowDuration;            /// Rotation's Following Duration.
    public float maxRotationFollowSpeed;            /// Maximum Rotation's Following Speed.
    [Space(5f)]
    public Vector3 up;                              /// Up Vector's Reference.
    [HideInInspector] public Vector3 forward;       /// Reoriented Forward's Vector.
    private Vector3 eulerOrbitRotation;             /// Current Orbit Rotation as Euler.
    private Vector3 displacementVelocity;           /// Displacement's Velocity.
    private Quaternion orbitRotation;               /// Orbit Rotation as Quaternion.
    private Quaternion rotationOffset;              /// Rotation's Offset as Quaternion.
    private Vector2 inputAxes;                      /// Input's Axes.
    private float currentDistance;                  /// Current Distance from Camera and Player.
    private float angularSpeed;                     /// Angular's Speed.

#region UnityMethods:
    /// <summary>Draws Gizmos on Editor mode.</summary>
    private void OnDrawGizmos()
    {
        Gizmos.color = Color.green;
        Gizmos.DrawRay(transform.position, up);
        Gizmos.color = Color.blue;
        Gizmos.DrawRay(transform.position, forward);

        if(target != null)
        {
            Gizmos.color = Color.cyan;
            Gizmos.DrawLine(target.position, GetOffsetPoint());

            if(!Application.isPlaying)
            {
                UpdateRotationOffset();
                ReorientForward();
            }

            Quaternion rotation = transform.rotation * rotationOffset;

            Handles.color = new Color(1.0f, 0.0f, 0.0f, 0.35f); /// Red
            Handles.DrawSolidArc(transform.position, transform.right, transform.forward, Vector3.Angle(transform.forward, rotation * Vector3.forward) * Mathf.Sign(eulerRotationOffset.x), 1.0f);
            Handles.color = new Color(0.0f, 1.0f, 0.0f, 0.35f); /// Green
            Handles.DrawSolidArc(transform.position, transform.up, transform.right, Vector3.Angle(transform.right, rotation * Vector3.right) * Mathf.Sign(eulerRotationOffset.y), 1.0f);
            Handles.color = new Color(1.0f, 0.0f, 1.0f, 0.35f); /// Blue
            Handles.DrawSolidArc(transform.position, transform.forward, transform.up, Vector3.Angle(transform.up, rotation * Vector3.up) * Mathf.Sign(eulerRotationOffset.z), 1.0f);

            if(!Application.isPlaying)
            {
                transform.position = GetOffsetPoint();
                transform.rotation = Quaternion.LookRotation(GetLookDirection()) * rotationOffset;
            }
        }
    }

    /// <summary>Resets GameplayCamera's instance to its default values.</summary>
    private void Reset()
    {
        up = Vector3.up;
    }

    /// <summary>GameplayCamera's tick at each frame.</summary>
    private void Update()
    {
        if(target == null) return;

        TrackInput();
        UpdateRotationOffset();

        if(followDisplacementAt == LoopType.Update) DisplacementFollow();
        if(followRotationAt == LoopType.Update) RotationFollow();
    }

    /// <summary>Updates GameplayCamera's instance at the end of each frame.</summary>
    private void LateUpdate()
    {
        if(target == null) return;

        if(followDisplacementAt == LoopType.LateUpdate) DisplacementFollow();
        if(followRotationAt == LoopType.LateUpdate) RotationFollow();

        ReorientForward();
    }

    /// <summary>Updates GameplayCamera's instance at each Physics Thread's frame.</summary>
    private void FixedUpdate()
    {
        if(target == null) return;

        if(followDisplacementAt == LoopType.FixedUpdate) DisplacementFollow();
        if(followRotationAt == LoopType.FixedUpdate) RotationFollow();
    }
#endregion

    /// <summary>Tracks Input.</summary>
    private void TrackInput()
    {
        inputAxes.x = Input.GetAxis("Mouse Y");
        inputAxes.y = Input.GetAxis("Mouse X");
    }

    /// <summary>Performs the Displacement's Following.</summary>
    private void DisplacementFollow()
    {
        if(inputAxes.sqrMagnitude > 0.0f) OrbitInAxes(inputAxes.x, inputAxes.y);

        switch(displacementFollowType)
        {
            case FollowingType.Instant:
            transform.position = GetOffsetPoint();
            break;

            case FollowingType.Smooth:
            transform.position = GetSmoothDisplacementFollowDirection();
            break;
        }
    }

    /// <summary>Performs the Rotation's Following.</summary>
    private void RotationFollow()
    {
        switch(rotationFollowType)
        {
            case FollowingType.Instant:
            transform.rotation = Quaternion.LookRotation(GetLookDirection()) * rotationOffset;
            break;

            case FollowingType.Smooth:
            transform.rotation = GetSmoothFollowRotation();
            break;
        }
    }

    /// <summary>Orbits Camera in Given Axes.</summary>
    /// <param name="x">X's Axis.</param>
    /// <param name="y">Y's Axis.</param>
    private void OrbitInAxes(float x, float y)
    {
        if((invertAxes | Axes.X) == invertAxes) x *= -1.0f;
        if((invertAxes | Axes.Y) == invertAxes) y *= -1.0f;

        float xRotation = (x * orbitSpeed.x * GetTimeDelta(displacementTimeDelta));
        float yRotation = (y * orbitSpeed.y * GetTimeDelta(displacementTimeDelta));

        eulerOrbitRotation.x = (limitOrbitAxes | Axes.X) == limitOrbitAxes ?
            Mathf.Clamp(eulerOrbitRotation.x + xRotation, minOrbitLimits.x, maxOrbitLimits.x) : eulerOrbitRotation.x + xRotation;
        eulerOrbitRotation.y = (limitOrbitAxes | Axes.Y) == limitOrbitAxes ?
            Mathf.Clamp(eulerOrbitRotation.y + yRotation, minOrbitLimits.y, maxOrbitLimits.y) : eulerOrbitRotation.y + yRotation;

        orbitRotation = Quaternion.Euler(eulerOrbitRotation);
    }

    /// <returns>Gets the smooth displacement following's Vector.</returns>
    private Vector3 GetSmoothDisplacementFollowDirection()
    {
        return Vector3.SmoothDamp
        (
            transform.position,
            GetOffsetPoint(),
            ref displacementVelocity,
            displacementFollowDuration,
            limitDisplacementFollow ? maxDisplacementFolowSpeed : Mathf.Infinity,
            GetTimeDelta(displacementTimeDelta)
        );
    }

    /// <summary>Gets Offset Point, with the Orbit's Rotation already combined.</summary>
    private Vector3 GetOffsetPoint()
    {
        Vector3 scaledOffset = displacementOffset.normalized * maxDistance;
        Vector3 point = target.position + (orbitRotation * (relativeDisplacementFollow ? target.rotation * scaledOffset : scaledOffset));

        if((ignoreDisplacementAxes | Axes.X) == ignoreDisplacementAxes) point.x = transform.position.x;
        if((ignoreDisplacementAxes | Axes.Y) == ignoreDisplacementAxes) point.y = transform.position.y;

        return point;
    }

    /// <returns>Looking Direction, taking into account the axes to ignore.</returns>
    private Vector3 GetLookDirection()
    {
        Vector3 direction = target.position - transform.position;

        if((ignoreRotationAxes | Axes.X) == ignoreRotationAxes) direction.x = transform.position.x;
        if((ignoreRotationAxes | Axes.Y) == ignoreRotationAxes) direction.y = transform.position.y;
        if((ignoreRotationAxes | Axes.Z) == ignoreRotationAxes) direction.z = transform.position.z;

        return direction;
    }

    /// <return>Following Rotation, with the Rotation's Offset already combined.</return>
    private Quaternion GetSmoothFollowRotation()
    {
        Quaternion rotation = Quaternion.LookRotation(GetLookDirection()) * rotationOffset;
        float angle = Quaternion.Angle(transform.rotation, rotation);

        if(angle > 0.0f)
        {
            float t = Mathf.SmoothDampAngle(
                angle,
                0.0f,
                ref angularSpeed,
                rotationFollowDuration,
                limitRotationFollow ? maxRotationFollowSpeed : Mathf.Infinity,
                GetTimeDelta(rotationTimeDelta)
            );
            return Quaternion.Slerp(transform.rotation, rotation, t);
        }

        return rotation;
    }

    /// <summary>Updates the Rotation's Offset Given the Wuler Representation.</summary>
    private void UpdateRotationOffset()
    {
        Quaternion rotation = Quaternion.Euler(eulerRotationOffset);
        rotationOffset = relativeRotationFollow ? target.rotation * rotation : rotation;
    }

    /// <summary>Reorients Forward's Vector.</summary>
    private void ReorientForward()
    {
        forward = Vector3.Cross(transform.right, up);
    }

    /// <summary>Gets Time's Delta.</summary>
    /// <param name="_pa">Time Delta's Type.</param>
    /// <returns>Time's Delta of the Given Type.</returns>
    private float GetTimeDelta(TimeDelta _timeDelta = TimeDelta.Default)
    {
        switch(_timeDelta)
        {
            case TimeDelta.Default: return Time.deltaTime;
            case TimeDelta.Fixed:   return Time.fixedDeltaTime;
            case TimeDelta.Smooth:  return Time.smoothDeltaTime;
            default:                return 0.0f;
        }
    }
}

```

I also made a quick Character's script for the sake of giving a quick example (the original Character script I have a has tons of dependencies). So its jump does not have cooldown, and it doesn't evaluate if it is grounded.

**Simple Character Movement's Script:**

```
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(Rigidbody))]
public class CharacterMovement : MonoBehaviour
{
    [SerializeField] private GameplayCamera camera;     /// Gameplay's Camera.
    [Space(5f)]
    [SerializeField] private KeyCode jumpKey;           /// Jump's KeyCode.
    [SerializeField] private KeyCode displacementKey;   /// Displacement's Key.
    [SerializeField] private float displacementSpeed;   /// Displacements Speed.
    [SerializeField] private float jumpForce;           /// Jump's Force .
    [SerializeField] private ForceMode mode;            /// Jump Force' sMode.
    private Rigidbody rigidbody;                        /// Rigidbody's Component.

#region UnityMethods:
    /// <summary>CharacterMovement's instance initialization.</summary>
    private void Awake()
    {
        rigidbody = GetComponent<Rigidbody>();
    }

    /// <summary>CharacterMovement's tick at each frame.</summary>
    private void Update ()
    {
        Vector3 axes = new Vector3
        (
            Input.GetAxis("Horizontal"),
            0.0f,
            Input.GetAxis("Vertical")
        );

        if(axes.sqrMagnitude > 0.0f)
        {
            transform.rotation = Quaternion.LookRotation(axes);
            transform.Translate(transform.forward * displacementSpeed * Time.deltaTime, Space.World);
        }
        if(Input.GetKeyDown(jumpKey)) Jump();
    }
#endregion

    /// <summary>Performs Jump.</summary>
    private void Jump()
    {
        rigidbody.AddForce(Vector3.up * jumpForce, mode);
    }
}

```

**What I Want to Know:**

If I am missing something, I am using the wrong functions, calling the functions in the wrong threads/orders, etc.

Please let me know if there is more information I have to provide.

# Answer
not enough repo for commenting yet, so writing here, because it's a common thing with jittering near the end-position (not sure if that is your problem because it's not stated in your question)

If your actual camera is approaching the end position and you're applying your next translation/rotation it may overshot by a fraction and in the next frame it does the same in the other direction. Basically shaking the image then. Normally (if you're not just lerping to the end position - which may jitter as well, because moving smaller and smaller fractions, rasterized to pixels int the end) you just have to define some "snaping threshold" which will set the position/rotation to the desired end position once that threshold is reached
> 0 votes

# Answer
Your `GetSmoothFollowRotation()` function is wrong.

`SmoothDampAngle` gives you an angle in degrees (0-360 or -180-180), but you're passing it as the interpolation parameter to `Quaternion.Slerp` that expects a unitless interpolation ratio 0-1. This is not geometrically meaningful and effectively discards any smoothness guarantees you were getting from `SmoothDampAngle`, allowing your camera to overshoot, backtrack to correct, and vibrate as a result.

A more correct way to use smooth damping for rotation would be to damp your look vector, then look at that:

```
Vector3 _lookDirection;
Vector3 _lookDirectionVelocity;

private Quaternion GetSmoothFollowRotation()
{
    _lookDirection = Vector3.SmoothDamp(
        _lookDirection,
        GetLookDirection(),
        ref _lookDirectionVelocity,
        rotationFollowDuration,
        maxRotationFollow,
        Time.deltaTime
    ).normalized;

    return Quaternion.LookRotation(_lookRotation) * rotationOffset;
}

```
> 0 votes

# Answer
Try updating you camera transformation in the MonoBehaviour.LateUpdate function.
> -1 votes

---
Tags: unity, c#, camera, quaternion, interpolation
---


# Question
Title: GLSL Shader r GL_INVALID_OPERATION from glUniform1f error with textureSize
For debug purposes I've minimised the shader to the following:

```
varying vec4 v_color;
varying vec2 v_texCoords;

uniform sampler2D u_texture;

void main() {
    // ivec2 size = textureSize(u_texture, 0);//throws error if this line is enabled

    gl_FragColor = v_color * texture2D(u_texture, v_texCoords);
}

```

So don't mind what it actually does at the moment. With the line commented out it works fine, and other shaders work fine, but with the line in I get the errors:

`[GLProfiler] Error GL_INVALID_OPERATION from glUniform2f`

`[GLProfiler] Error GL_INVALID_OPERATION from glUniform1f`

`[GLProfiler] Error GL_INVALID_OPERATION from glUniformMatrix4fv`

# Answer
The reason it does not work is because I'm using LibGDX and by default the opengl version is 2 which is not compatible with the function `textureSize`. A workaround is to input the texture size using a `uniform` variable.

```
varying vec4 v_color;
varying vec2 v_texCoords;

uniform sampler2D u_texture;
uniform vec2 resolution;//texture resolution is fed to the shader here

void main() {
    // ivec2 size = textureSize(u_texture, 0);//no need for this line

    gl_FragColor = v_color * texture2D(u_texture, v_texCoords);
}

```
> 1 votes

---
Tags: shaders, glsl, vertex-shader
---


# Question
Title: What's the difference between post-processing, multi-pass rendering and compositing?
I initially thought that the word "post-processing" referred specifically to the set of techniques aimed at improving a rendered image (like antialiasing, depth of field, bloom and others) while "multi-pass rendering" or "compositing" both referred to the entire process used a creating an image (including any post-processing effects).

But, according to Wikipedia, the word "post-processing" also includes the techniques used to build a rendered image like shadow mapping. Which makes me wonder if all those words actually refer to the same thing.

# Answer
> 1 votes
Multi pass rendering, although it is used in other scenarios, nowadays is typically used to describe a way to render stereoscopic images. Multi pass means that depth rendering and other initial calculations for rendering to each eye are done separately for each eye (more than one pass= multi). Some newer methods are more performant by doing a single pass on these calculations for both eyes at once.

One single pass is typically more performant than multi pass. However, this optimization comes with some hits to flexibility. It’s more difficult to do different rendering to each eye.

Post processing typically refers to anything you do to the rendered image after rendering occurs. So you could do post-processing on either multipass rendered images or single pass images. Some typical post processing effects include exposure, bloom, tinting, split toning etc. although there are a huuuuge array of different things you can do in post processing.

Compositing usually involves combining multiple rendered image to form a single result. For example you may overlay one rendered image on top of another. Portal effects typically use compositing. The area of the primary view image that is taken up by the portal is replaced by the image rendered from a secondary viewpoint that is viewing the scene at a different location. These two viewpoints are composited to create the resulting effect.

---
Tags: rendering, terminology, post-processing
---


# Question
Title: How to read Unity Ads initialization code structure?
It is my first time integrating Unity ads into my game and my first time encountering the sample code below with the usage of "?" and ":" and wanted to ask how to read the line of code below specifically the way it assigns the \_gameId.

```
public void InitializeAds()
{
    _gameId = (Application.platform == RuntimePlatform.IPhonePlayer)
        ? _iOSGameId
        : _androidGameId;

    Advertisement.Initialize(_gameId, _testMode, this);
}

```

# Answer
> 1 votes
This code uses the C# ternary operator.

This construct consists of three parts. A condition and two values.

```
<condition> ? <value_true> : <value_false>

```

When the condition is true, this construct returns the first value. When the condition is false, it returns the second value.

So what happens here is that the condition `Application.platform == RuntimePlatform.IPhonePlayer` is being evaluated. When it is true, then `_gameId` gets set to `_iOSGameId`. When it is false, then `_gameId` gets set to `_androidGameId`.

If you feel uncomfortable with ternary expression, then you could also write the whole method as this:

```
public void InitializeAds()
{
    if(Application.platform == RuntimePlatform.IPhonePlayer)
    {
        _gameId = _iOSGameId;
    }
    else
    {
        _gameId = _androidGameId;
    }

    Advertisement.Initialize(_gameId, _testMode, this);
}

```

What's immediately visible here is that any platform except iPhone is assumed to be Android. I am not familiar with the Unity ingame advertisement API, but this has some obvious code smell to me.

---
Tags: unity, c#, unity-ads
---


# Question
Title: Does Raycast called from Update execute on next FixedUpdate?
I've been searching through the Unity docs (https://docs.unity3d.com/ScriptReference/Physics.Raycast.html), but no matter where I look, I couldn't find exact behaviour of Physics.Raycast() method.

I've seen a lot of youtube videos using Physics.Raycast inside Update loop , so I started questioning behaviour of Physics.Raycast() method. (I discovered this vague unwritten rule: "If you use raycasts to ping objects it's okay to put it inside Update loop", same thing with Rigidbody.AddForce(x,y,z, ForceMode.Impulse) - apparently it's fine to use it inside Update)

So my question is: if I call Physics.Raycast() inside Update() does it execute immediately or does it get queued for execution on the next FixedUpdate frame? (documentation is missing explanation for this)

If it's the latter, how can I know which Physics methods get queued for the next FixedUpdate , and which happen instantly?

# Answer
> 2 votes
The raycast is executed as soon as you call the function. In fact, you are normally going to want to use the result of the raycast inside of the same update, and that just wouldn't be possible if the execution was delayed.

Now, I'm not an expert on how the physics engine works under the hood, but my understanding is that you can interact with physics objects at any point, not just `FixedUpdate`. The thing is that the changes that you make (adding a force to a rigidbody, for example) are not going to affect anything until the pyhisics engine runs its own internal update (which happens right after `FixedUpdate`). So, if you add a force in `Update`, and during the next frame (assuming the `FixedUpdate` has not happenend yet) you check the velocity of the object, you will see that it has not changed at all. But once the physics engine updates, it will work the same way as if you had added the force in `FixedUpdate`.

TL;DR is there is nothing magic about `FixedUpdate`, it simply is a way to execute your code right before the internal physics loop update.

---
Tags: unity, physics, raycasting
---


# Question
Title: Using CommonUI Plugin in Unreal Engine5 does not show any option in PlatformInput
As shown in the following screenshot, the menu **Platform Input** does not show any information and does not allow any customization.

Following the steps in this video the options are necessary to configure part of the UI key binding, they should be visible as you can see at minute 38:50 or in the following screenshot: .

Does anyone know if this is a bug or am I missing some piece? Does not seem to be required any other plugin.

# Answer
The issue wasn't a bug, I had to enable at least one platform to make those settings appear. It requires, also, to delete temporary files such as **Binary** folder and then recreating the source project files and recompile the project.
> 1 votes

---
Tags: unreal, plugin
---


# Question
Title: SDL2 - Camera only scrolls in x direction, but not y direction
I'm following along with the LazyFoo tutorial to create the basis for a simple arcade space shooter. I'm trying to get the sprite moving through the map while being tracked by the camera. The code I have works in the x direction but doesn't scroll/follow in the y direction. I can't figure out why because the code for both directions is the same.

Here's what I have, the camera function is at the bottom (line 300ish) in the main function.

#include <iostream>
#include <stdio.h>
#include <SDL2/SDL.h>
#include <sstream>
#include <string>
#include <SDL2/SDL_image.h>

SDL_DisplayMode current;

const int LEVEL_WIDTH = 1280;
const int LEVEL_HEIGHT = 960;
int SCREEN_WIDTH = 1000;
int SCREEN_HEIGHT = 1000;

SDL_Window* gWindow = NULL;

SDL_Surface* gScreenSurface = NULL;

SDL_Texture* ship = NULL;

SDL_Renderer* gRenderer = NULL;

//Texture wrapper class
class LTexture
{
    public:
        //Initializes variables
        LTexture();

        //Deallocates memory
        ~LTexture();

        //Loads image at specified path
        bool loadFromFile( std::string path );

        //Deallocates texture
        void free();

        //Renders texture at given point
        void render( int x, int y, SDL_Rect* clip = NULL, double angle = 0.0, SDL_Point* center = NULL, SDL_RendererFlip = SDL_FLIP_NONE );

        //Gets image dimensions
        int getWidth();
        int getHeight();
        void setWidth( int width );
        void setHeight( int height );

        private:

        //The actual hardware texture

        SDL_Texture* mTexture;

        //Image dimensions
        int mWidth;
        int mHeight;
};

LTexture::LTexture() {

    mTexture = NULL;
    mWidth = 0;
    mHeight = 0;

}

LTexture::~LTexture() {
    free();
}

bool LTexture::loadFromFile( std::string path ) {

    free();

    SDL_Texture* newTexture = NULL;

    SDL_Surface* loadedSurface = IMG_Load( path.c_str() );
//  SDL_SetColorKey( loadedSurface, SDL_TRUE, SDL_MapRGB( loadedSurface->format, 0, 0xFF, 0xFF ) );

    newTexture = SDL_CreateTextureFromSurface( gRenderer, loadedSurface);

    mWidth = loadedSurface->w;
    mHeight = loadedSurface->h;

    SDL_FreeSurface( loadedSurface );

    mTexture = newTexture;
    return mTexture != NULL;
}

void LTexture::free() {

    if (mTexture != NULL) {
        SDL_DestroyTexture( mTexture );
        mTexture = NULL;
        mWidth = 0;
        mHeight = 0;
    }
}

void LTexture::render( int x, int y, SDL_Rect* clip, double angle, SDL_Point* center, SDL_RendererFlip flip ) {

    SDL_Rect renderQuad = { x, y, mWidth, mHeight };

    if ( clip != NULL ) {
        renderQuad.h = clip->h;
        renderQuad.w = clip->w;
    }

    SDL_RenderCopyEx( gRenderer, mTexture, clip, &renderQuad, angle, center, flip );
}

int LTexture::getWidth() {
    return mWidth;
}

int LTexture::getHeight() {
    return mHeight;
}

void LTexture::setWidth( int width ) {
    mWidth = width;
}

void LTexture::setHeight( int height ) {
    mHeight = height;
}

class Ship {

    public:
        // Ship dimensions
        const static int SHIP_HEIGHT = 100;
        const static int SHIP_WIDTH = 100;

        // Ship maximum velocity
        static const int SHIP_VELOCITY = 10;

        Ship();

        void handleEvent( SDL_Event &e );

        int getVelY();
        int getVelX();
        int getPosX();
        int getPosY();

        void move();

        void render( int camX, int camY );

    private:
        int mPosX, mPosY;
        int mVelX, mVelY;

};

LTexture shipTexture;
LTexture backgroundTexture;

Ship::Ship() {

    mPosX = 0;
    mPosY = 0;
    mVelX = 0;
    mVelY = 0;
}

int Ship::getVelY() {
    return mVelY;
}

int Ship::getVelX() {
    return mVelX;
}

void Ship::handleEvent( SDL_Event &e ) {

    if ( e.type == SDL_KEYDOWN && e.key.repeat == 0 ) {

        switch (e.key.keysym.sym) {
            case SDLK_UP: mVelY -= SHIP_VELOCITY; break;
            case SDLK_DOWN: mVelY += SHIP_VELOCITY; break;
            case SDLK_LEFT: mVelX -= SHIP_VELOCITY; break;
            case SDLK_RIGHT: mVelX += SHIP_VELOCITY; break;
        }
    }

    else if ( e.type == SDL_KEYUP && e.key.repeat == 0 ) {

        switch (e.key.keysym.sym) {
            case SDLK_UP: mVelY += SHIP_VELOCITY; break;
            case SDLK_DOWN: mVelY -= SHIP_VELOCITY; break;
            case SDLK_LEFT: mVelX += SHIP_VELOCITY; break;
            case SDLK_RIGHT: mVelX -= SHIP_VELOCITY; break;
        }
    }
}

void Ship::move() {

    mPosX += mVelX;

    if ( mPosX < 0 || mPosX + SHIP_WIDTH > LEVEL_WIDTH ) {
        mPosX -= mVelX;
    }

    mPosY += mVelY;

    if ( mPosY < 0 || mPosY + SHIP_HEIGHT > LEVEL_HEIGHT ) {
        mPosY -= mVelY;
    }

}

void Ship::render( int camX, int camY ) {

    double angle;

    if ( mVelX > 0 )
        angle = 90.0;
    if ( mVelX < 0 )
        angle = 270.0;
    if ( mVelY > 0 )
        angle = 180.0;
    if ( mVelY < 0 )
        angle = 0.0;

    shipTexture.render( mPosX - camX, mPosY - camY, NULL, angle, NULL );

}

int Ship::getPosX() {
    return mPosX;
}

int Ship::getPosY() {
    return mPosY;
}

void init() {

    // Load window and associates surface
    SDL_Init( SDL_INIT_VIDEO );
    gWindow = SDL_CreateWindow ( "Video Game v1.0", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
    gRenderer = SDL_CreateRenderer ( gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC );

    SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
    // Enable PNG loading
    int imgFlags = IMG_INIT_PNG;
    IMG_Init( imgFlags );

    // Format screen size
    SDL_DisplayMode current;
    SDL_GetCurrentDisplayMode(0, &current );
    SCREEN_WIDTH = current.w;
    SCREEN_HEIGHT = current.h;
    SDL_Log("Display #%d: current display mode is %dx%dpx @ %dhz.", 0, current.w, current.h, current.refresh_rate);

}

void loadMedia() {

    shipTexture.loadFromFile( "8.png" );
    backgroundTexture.loadFromFile( "509906.png" );
    backgroundTexture.setWidth( SCREEN_WIDTH );
    backgroundTexture.setHeight( SCREEN_HEIGHT );
}

void close() {

    shipTexture.free();

    SDL_DestroyWindow( gWindow );
    gWindow = NULL;

    SDL_DestroyRenderer( gRenderer );
    gRenderer = NULL;

    SDL_Quit();
    IMG_Quit();

}

int main( int argc, char* args[] ) {

    bool quit = false;
    SDL_Event e;
    Ship ship;
    SDL_Rect camera = { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT };
    init();
    loadMedia();

    while( !quit ) {

        while ( SDL_PollEvent( &e ) !=0 ) {
            if( e.type == SDL_QUIT ) {
                quit = true;
            }
            ship.handleEvent( e );
        }

        ship.move();

        camera.x = ( ship.getPosX() + Ship::SHIP_WIDTH / 2 ) - SCREEN_WIDTH / 2;
        camera.y = ( ship.getPosY() + Ship::SHIP_HEIGHT / 2 ) - SCREEN_HEIGHT / 2;

        if ( camera.x < 0 )
            camera.x = 0;
        if ( camera.y < 0 )
            camera.y = 0;
        if ( camera.x > LEVEL_WIDTH - camera.w )
            camera.x = LEVEL_WIDTH - camera.w;
        if ( camera.y > LEVEL_HEIGHT - camera.h )
            camera.y = LEVEL_HEIGHT - camera.h;

        // Clear the screen
        SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
        SDL_RenderClear( gRenderer );

        backgroundTexture.render( 0, 0, &camera );
        ship.render( camera.x, camera.y );

        // Update screen
        SDL_RenderPresent( gRenderer );

    }

    close();

    return 0;
}

```
</code></pre>

# Answer
> 1 votes
Assuming

```
LEVEL_HEIGHT = 960
camera.h = SCREEN_HEIGHT = 1000

```

And the code

```
if ( camera.y > LEVEL_HEIGHT - camera.h )

```

We can deduce that

```
range_of_action = LEVEL_HEIGHT - camera.h = 960 - 1000 = -40

```

We can conclude that the camera will always be at -40.

Your level is smaller than the field where you can scroll your camera.

To fix this, give more room for your camera to move, increase the size of your level.

---
Tags: camera, sdl2
---


# Question
Title: Set a minimum distance with navmeshagent
I am totally newb. How to set a minimum distance between AI chasing a player if AI has navmeshagent

```
        if (Vector3.Distance(transform.position, target.position) > minDistance)
        {
            enemy.destination = player.position;
        }

```

What I need is it works similar to this code below:

```
if (Vector3.Distance(transform.position, player.position) > minDistance)
{
    transform.position = Vector3.MoveTowards(transform.position, player.position, moveSpeed*Time.deltaTime);
}

```

But using destination property or SetDestination

# Answer
After DMGregory's comment, I'm rethinking my answer. You are already on a right way, actually.

Let's say some other script assign target (the player) to your `NavMeshAgent` (enemy). It can be done through public variable or through a method. As your target is assigned, you want to check, what is the distance left to it and if it is smaller than some threshold (`minDistanceSqr` in example below). If it is - you want to stop your agent from moving. Otherwise - continue following.

Now, if no ideas are present, here's a snippet that SHOULD (not tested) work. In your enemy script you want to add:

```
public Transform target;
public float minDistanceSqr;

private NavMeshAgent _agent;

private void Awake()
{
    _agent = GetComponent<NavMeshAgent>();
}

private void Update()
{
    if (target != null)
    {
        var destPosition = target.position;
        var sqrDistance = (transform.position - destPosition).sqrMagitude;

        _agent.destination = destPosition;
        _agent.isStopped = (sqrDistance <= minDistanceSqr);
    }
    else
    {
        _agent.isStopped = true;
    }
}

```

As other answer suggest changing velocity to 0, it actually won't stop agent from calculating path to your target, thus it will be using unnecessary CPU cycles.

---

### Old (and wrong) answer (leaving for educational purposes)

When setting target position, just add offset to the actual target:

1. calculate direction from your agent to desired target and normalize it
`var offsetDirection = (player.transform.position - enemy.transform.position).normalized;`
2. have a *float* type variable which sets the desired offset distance
`var offsetDistance = 1f;`
3. set destination with offset:
`enemy.destination = (player.position + offsetDirection * offsetDistance);`
> 1 votes

# Answer
else { agent.velocity = Vector3.zero; }
> -1 votes

# Answer
Similar solution:

agent.stoppingDistance = *float value*
> -2 votes

---
Tags: unity
---