### 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.
Building an Efficient 2D Scene Graph for Object Transformation and Hierarchical Management
- paypal56_ab6mk6y7
- Site Admin
- Posts: 72
- Joined: Sat Oct 26, 2024 3:05 pm
- paypal56_ab6mk6y7
- Site Admin
- Posts: 72
- Joined: Sat Oct 26, 2024 3:05 pm
Re: Building an Efficient 2D Scene Graph for Object Transformation and Hierarchical Management
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
```
### **SceneGraph Class Implementation**
```cpp
```
### **Main Program Logic**
```cpp
```
### **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.
### **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.