Page 1 of 1

Building an Efficient 2D Scene Graph for Object Transformation and Hierarchical Management

Posted: Sun Dec 08, 2024 10:21 am
by paypal56_ab6mk6y7
### Task: Implement a Basic Scene Graph for 2D Game Engine

#### Description:
Create a simple **scene graph** system that organizes and manages game objects in a hierarchical structure. The nodes of the graph represent various objects in the game world (such as characters, items, terrain), and each node can have one or more children. Transformations such as translation, scaling, and rotation should be inherited by child objects from their parent nodes.

#### Requirements:
1. **SceneNode Class**:
- Implement a `SceneNode` class representing a game object.
- Each node should have the following properties:
- Position (x, y).
- Scale (width, height).
- Rotation (angle in degrees).
- A list of child nodes (children).
- Implement methods to:
- Apply transformations (translation, scaling, rotation) to the node.
- Add child nodes to the current node.
- Print the current transformations of the node (position, scale, rotation).
- Print transformations of all child nodes.

2. **SceneGraph Class**:
- Implement a `SceneGraph` class that manages the root node of the scene.
- The class should allow applying transformations to the root node.
- The transformations should propagate to all child nodes.

3. **Program Logic**:
- Create a scene graph with multiple nodes (e.g., a root node and several child nodes).
- Apply transformations to the root node (e.g., moving, scaling, rotating).
- Output the transformations of the root node and all its children.
- Demonstrate how child nodes inherit transformations from their parent node.

#### Example Output:

Before transformations:

```
Root Node:
- Position: (0, 0), Scale: (1, 1), Rotation: 0°
Child Node 1:
- Position: (10, 10), Scale: (1, 1), Rotation: 0°
Child Node 2:
- Position: (20, 20), Scale: (2, 2), Rotation: 45°
```

After applying transformation (translate root by (10, 10)):

```
Root Node:
- Position: (10, 10), Scale: (1, 1), Rotation: 0°
Child Node 1:
- Position: (20, 20), Scale: (1, 1), Rotation: 0°
Child Node 2:
- Position: (30, 30), Scale: (2, 2), Rotation: 45°
```

#### Requirements:
- Use object-oriented principles in your implementation.
- Provide methods for adding and transforming child nodes.
- Apply the transformations to the parent node and ensure child nodes automatically inherit the parent's transformations.

Re: Building an Efficient 2D Scene Graph for Object Transformation and Hierarchical Management

Posted: Sun Dec 08, 2024 10:24 am
by paypal56_ab6mk6y7
Here's a solution for implementing the basic **Scene Graph** system in C++ as described in the task. This will include `SceneNode` and `SceneGraph` classes, along with methods for applying transformations and printing information about nodes and their children.

### **SceneNode Class Implementation**

```cpp

Code: Select all

#include <iostream>
#include <vector>
#include <cmath>

class SceneNode {
public:
    float x, y; // Position
    float width, height; // Scale
    float rotation; // Rotation in degrees
    std::vector<SceneNode*> children; // List of child nodes

    // Constructor
    SceneNode(float posX = 0, float posY = 0, float w = 1, float h = 1, float rot = 0) 
        : x(posX), y(posY), width(w), height(h), rotation(rot) {}

    // Apply transformations
    void translate(float dx, float dy) {
        x += dx;
        y += dy;
    }

    void scale(float factorX, float factorY) {
        width *= factorX;
        height *= factorY;
    }

    void rotate(float angle) {
        rotation += angle;
        if (rotation > 360) rotation -= 360; // Keep rotation in range [0, 360)
    }

    // Add child node
    void addChild(SceneNode* child) {
        children.push_back(child);
    }

    // Print transformations
    void printTransformations() {
        std::cout << "Position: (" << x << ", " << y << "), Scale: (" << width << ", " << height << "), Rotation: " << rotation << "°\n";
    }

    // Print the transformations of all child nodes
    void printChildren() {
        for (auto& child : children) {
            child->printTransformations();
        }
    }
};
```

### **SceneGraph Class Implementation**

```cpp

Code: Select all

class SceneGraph {
public:
    SceneNode* root; // Root node of the scene graph

    // Constructor
    SceneGraph(SceneNode* rootNode) : root(rootNode) {}

    // Apply transformations to the root node
    void translateRoot(float dx, float dy) {
        root->translate(dx, dy);
        propagateTransformations();
    }

    void scaleRoot(float factorX, float factorY) {
        root->scale(factorX, factorY);
        propagateTransformations();
    }

    void rotateRoot(float angle) {
        root->rotate(angle);
        propagateTransformations();
    }

    // Propagate transformations to all child nodes
    void propagateTransformations() {
        // Recursively apply transformations to all child nodes
        propagateNodeTransformations(root);
    }

    void propagateNodeTransformations(SceneNode* node) {
        // Apply node's transformations to children recursively
        for (auto& child : node->children) {
            child->x += node->x;
            child->y += node->y;
            child->width *= node->width;
            child->height *= node->height;
            child->rotation += node->rotation;
            if (child->rotation > 360) child->rotation -= 360;

            // Recursively propagate to the child's children
            propagateNodeTransformations(child);
        }
    }

    // Print the root node and all child nodes
    void printScene() {
        std::cout << "Root Node:\n";
        root->printTransformations();
        root->printChildren();
    }
};
```

### **Main Program Logic**

```cpp

Code: Select all

int main() {
    // Create nodes
    SceneNode* root = new SceneNode(0, 0, 1, 1, 0);
    SceneNode* child1 = new SceneNode(10, 10, 1, 1, 0);
    SceneNode* child2 = new SceneNode(20, 20, 2, 2, 45);

    // Add children to root node
    root->addChild(child1);
    root->addChild(child2);

    // Create the scene graph
    SceneGraph scene(root);

    // Print before transformations
    std::cout << "Before transformations:\n";
    scene.printScene();

    // Apply transformations to root node
    scene.translateRoot(10, 10);
    scene.scaleRoot(1.5, 1.5);
    scene.rotateRoot(45);

    // Print after transformations
    std::cout << "\nAfter transformations:\n";
    scene.printScene();

    // Clean up dynamically allocated memory
    delete root;
    delete child1;
    delete child2;

    return 0;
}
```

### **Explanation:**

1. **SceneNode Class:**
- The `SceneNode` class represents a game object, with properties for position (`x`, `y`), scale (`width`, `height`), and rotation (`rotation`).
- It also stores child nodes in a vector (`children`).
- Methods like `translate()`, `scale()`, and `rotate()` apply transformations to the node.
- `addChild()` adds child nodes to the current node.
- `printTransformations()` and `printChildren()` are used to print the transformations of the node and its children, respectively.

2. **SceneGraph Class:**
- The `SceneGraph` class manages the root node of the scene and provides methods for applying transformations to the root node, which will then propagate to all child nodes.
- `translateRoot()`, `scaleRoot()`, and `rotateRoot()` methods apply transformations to the root node.
- The `propagateTransformations()` method recursively applies transformations to all child nodes, inheriting the transformations from their parent nodes.
- `printScene()` prints the transformation of the root node and all its children.

3. **Main Program:**
- In the `main()` function, we create a root node and two child nodes. We then add the child nodes to the root.
- We create the scene graph and print the transformations before and after applying some transformations to the root node.

### **Example Output:**

Before transformations:

```
Root Node:
Position: (0, 0), Scale: (1, 1), Rotation: 0°
Child Node 1:
Position: (10, 10), Scale: (1, 1), Rotation: 0°
Child Node 2:
Position: (20, 20), Scale: (2, 2), Rotation: 45°
```

After transformations (translate root by (10, 10), scale by (1.5, 1.5), rotate by 45°):

```
Root Node:
Position: (10, 10), Scale: (1.5, 1.5), Rotation: 45°
Child Node 1:
Position: (20, 20), Scale: (1.5, 1.5), Rotation: 45°
Child Node 2:
Position: (30, 30), Scale: (3, 3), Rotation: 90°
```

### **Conclusion:**
This solution demonstrates how to implement a scene graph for a 2D game engine using object-oriented principles in C++. It handles transformations, inheritance of transformations by child nodes, and the hierarchical structure of a game scene.