Skip to content

Commit

Permalink
Db generation and bug fix in summary
Browse files Browse the repository at this point in the history
  • Loading branch information
TomRuisseau committed Jul 17, 2024
1 parent 2523e45 commit 9cae4a3
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 29 deletions.
217 changes: 197 additions & 20 deletions src/Doc/Steps/db.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,213 @@
# Database Generation
## Save Camera view

In the runtime, the main camera view will be automatically saved in the path you specify. The camera view will be saved as a .png file with the date and time as the file name.
There is a parameter where you can set the number of screenshots you want to save per room. The default value is 5.
After the room is generated, the data is collected in the ```DatabaseGenerator.cs``` script. Each steps will be detailed in the following sections.

## Camera parameters
## Camera placement

The camera can be adjusted with the following parameters:
First, all the empty nodes are retrieved from the room's quad tree. The camera is the placed randomly in one of them, and a random rotation is applied according to the settings. We then ensure that the camera is not placed too close to the walls, the ceiling or to props to avoid clipping issues. This is done by creating a collider sphere around it and checking for collisions.

- **Field of view**: The field of view of the camera. The default value is 90.
- **ISO**: The ISO of the camera.
- **Focus distance**: The shutter speed of the camera.
- **Aperture**: The aperture of the camera. The default value is 5.6.

- **Camera rotation**: Define the maximum rotation of the camera in degrees. By default, the camera will on all axes.

## Take a screenshot
## Save Camera view

To take a screenshot of the camera view, you can use the following code:
Secondly, a screenshot is generated using this custom method in ```CameraScreenshot.cs``` which allow to save the camera view while ignoring the UI.

```Csharp
using UnityEngine;
using CameraScreenshot;
private IEnumerator Capture()
{
// Create a RenderTexture to save the camera view
RenderTexture rt = new RenderTexture(imageWidth, imageHeight, 24);
cameraToCapture.targetTexture = rt;

public class CameraScreenshotExample : MonoBehaviour
{
[SerializeField] private CameraScreenshot cameraScreenshot;
void Start()
// Create a 2D texture to save the screenshot
Texture2D screenShot = new Texture2D(imageWidth, imageHeight, TextureFormat.RGB24, false);
cameraToCapture.Render();

// Activate the RenderTexture and read the pixels
RenderTexture.active = rt;
screenShot.ReadPixels(new Rect(0, 0, imageWidth, imageHeight), 0, 0);
screenShot.Apply();

// Reset the camera and RenderTexture
cameraToCapture.targetTexture = null;
RenderTexture.active = null;
Destroy(rt);

// Save the screenshot
byte[] bytes = screenShot.EncodeToPNG();
File.WriteAllBytes(savePath, bytes);
yield return null;
}
```

## Data collection

Finally, the data about each openings in the image is collected :

#### Distance

The distance from the camera is calculated by substrating the camera position from the opening position.

#### Angle

The quaternion angle between the camera and the opening is calculated using the ```Quaternion.LookRotation()``` method.

#### Dimensions

The dimensions of the opening are calculated by using the ```Bounds.size``` property of the opening's collider.

#### Bounding boxes

##### Full bounding box

The bounding box is the 2D rectangle that contains the opening. It is calculated by using the ```Bounds.min``` and ```Bounds.max``` properties of the opening's collider in the ```Openings.cs``` script.

##### Visibility bounding box

The visibility bounding box is the 2D rectangle that contains only the visible part of the opening. It is calculated by casting numerous rays from the camera to the opening and finding the intersection points. The bounding box is then calculated using the intersection points in the ```Openings.cs``` script.

````Csharp
public BoundingBox2D GetVisibilityBoundingBox()
{
gameObject.TryGetComponent<BoxCollider>(out BoxCollider openingBounds);
_width = RoomsGenerator.GetOpeningWidth(openingBounds.size);
_height = openingBounds.size.y;
int minX = Screen.width + 1;
int maxX = -1;
int minY = Screen.height + 1;
int maxY = -1;

float widthStep = _width / Mathf.Sqrt(NumberOfPoints);
float heightStep = _height / Mathf.Sqrt(NumberOfPoints);

for (float x = -_width / 2f + widthStep / 2; x < _width / 2f; x += widthStep)
{
for (float y = -_height / 2f + heightStep / 2; y <= _height / 2f; y += heightStep)
{
var thisTransform = transform;
Vector3 positionOffset = thisTransform.right * x + thisTransform.up * y;
Vector3 aimPoint = GetCenter() + positionOffset;
if (IsPointVisible(aimPoint) && IsPointOnScreen(aimPoint))
{
Vector3 screenPoint = _mainCamera.WorldToScreenPoint(aimPoint);
minX = (int)Mathf.Min(minX, screenPoint.x);
maxX = (int)Mathf.Max(maxX, screenPoint.x);
minY = (int)Mathf.Min(minY, screenPoint.y);
maxY = (int)Mathf.Max(maxY, screenPoint.y);
}
}
}
// 640 * 360 is the minimum resolution
int screenShotWidth = 640 * MainMenuController.PresetData.Resolution;
int screenShotHeight = 360 * MainMenuController.PresetData.Resolution;

// Scale coordinates to screenshot size
minX = (int)(minX * screenShotWidth / Screen.width);
maxX = (int)(maxX * screenShotWidth / Screen.width);
minY = (int)(minY * screenShotHeight / Screen.height);
maxY = (int)(maxY * screenShotHeight / Screen.height);


return new BoundingBox2D(new Vector2Int(minX, minY), maxX - minX, maxY - minY);
}

private bool IsPointVisible(Vector3 aimPoint)
{
cameraScreenshot.savePath = Application.dataPath + "/yourPath";
cameraScreenshot.CaptureScreenshot();
GameObject mainCamera = _mainCamera!.gameObject;
Vector3 aimPointDirection = aimPoint - mainCamera.transform.position;

if (Physics.Raycast(mainCamera.transform.position, aimPointDirection, out var hit, float.MaxValue))
{
if (hit.collider.gameObject == gameObject || hit.collider.gameObject.transform.parent == transform)
return true;
}

return false;
}

// Check if a point is on the screen, i.e. in the camera's view frustum
private bool IsPointOnScreen(Vector3 point)
{
Vector3 screenPoint = _mainCamera!.WorldToViewportPoint(point);
return screenPoint.x is > 0 and < 1 && screenPoint.y is > 0 and < 1 && screenPoint.z > 0;
}
````

#### Visibility ratio

The visibility ratio is the ratio of the visibility bounding box area over the full bounding box area. The data is only kept if the visibility ratio is different from 0, to avoid collecting data from openings that are not visible in the image.

## Save data

The screenshot is then saved, along with a matching JSON file containing the collected data about openings, the seed and the camera information. The JSON file is structured as follows:

```json
{
"SeedsData": {
"DatabaseSeed": 522732214,
"RoomsSeed": -320021519,
"OpeningsSeed": 723920686,
"ObjectsSeed": 1119647337
},
"CameraData": {
"FieldOfView": 52.2338448,
"NearClipPlane": 0.3,
"FarClipPlane": 1000.0,
"ViewportRectX": 0.0,
"ViewportRectY": 0.0,
"ViewportRectWidth": 1920,
"ViewportRectHeight": 1080,
"Depth": -1.0,
"IsOrthographic": false
},
"ScreenshotData": {
"OpeningsData": [
{
"Type": "Window",
"Dimensions": {
"Height": 1.603815,
"Width": 1.13412368,
"Thickness": 0.10204263
},
"DistanceToCamera": 7.12805271,
"RotationQuaternionFromCamera": {
"w": 0.457306623,
"x": -0.004237673,
"y": 0.8892608,
"z": 0.008240416
},
"OpenessDegree": 0.6515185,
"VisibilityRatio": 0.9289916,
"BoundingBox": {
"Origin": [
1118,
454
],
"Dimension": [
118,
205
]
},
"VisibilityBoundingBox": {
"Origin": [
1120,
458
],
"Dimension": [
116,
200
]
}
},
],
"CameraRotation": {
"w": 0.5645235,
"x": 0.0,
"y": 0.825417,
"z": 0.0
}
}
}
```

A JSON is also created for each room, containing the seeds, the room's dimensions, the generation's time and the placement data.
8 changes: 4 additions & 4 deletions src/Doc/Steps/props.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Props placement

### Quad tree
## Quad tree

The props are placed in the room using a quad tree : the space is divided into four equal nodes, which represent rectangles in the room. The props are placed one by one randomly in one of the biggest empty nodes, namely the empty nodes with the lowest depth. The node chosen is then divided into four nodes once again. The process is repeated until all the props are placed inside the room. This ensures that the props have the highest chance of being placed without overlapping with other props, thus limiting the number of tries needed to place them.

Expand All @@ -10,7 +10,7 @@ The props are placed in the room using a quad tree : the space is divided into f
<em>Figure: 3 steps of the quad tree division process for prop placement.</em>
</p>

### Optimal nodes
## Optimal nodes

For certain types of furnitures, the node choice is not fully random and follow some rules. This allows to place the furniture in a more realistic way. Thus, to generate other kind of rooms, you would have to add new types of furniture and new sets of rules.

Expand All @@ -20,15 +20,15 @@ Cuurently there are 2 main rules :

They are implemented in the ```QuadTreeNode.cs``` script.

### "Spawner" props
## Spawner props

Some props place other props around them when they are instantiated. This helps having a coherent placement, while still having a random aspect. The props instancianting other props are the following :

- **TV stands** : They place a random TV on top of them, with a small angle.
- **Tables** : They place a random amount of chairs around them, and make them face the table.
- **Desk** : They place a random armchair in front of them.

### Add a prop
## Add a prop

To create a new prop prefab, the game object needs some mandatory components :
- **A mesh** : The visual representation of the prop.
Expand Down
2 changes: 1 addition & 1 deletion src/Doc/build.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ Then, you can build the project by going to `File > Build Settings` and selectin
Windows is the only build target that has been tested, but building for other platforms should work as well using the correct [Unity plugins](https://docs.unity3d.com/560/Documentation/Manual/PluginsForDesktop.html).


> :warning: The .exe will not work if not associated with the other files created by Unity.
> Note that the .exe will not work if not associated with the other files created by Unity.
2 changes: 1 addition & 1 deletion src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
- [Generation steps](./Doc/./Steps/steps_menu.md)
- [Room generation](./Doc/./Steps/room.md)
- [Props placement](./Doc/./Steps/props.md)
- [Data recovery](./Doc/./Steps/room.md)
- [Data recovery](./Doc/./Steps/db.md)

# Testing

Expand Down
6 changes: 3 additions & 3 deletions src/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ Each screenshot is matched with a Json containing info about the room, the seeds
}
```

## Open source
## Work on ISGT

ISGT is fully open-source, you can fork the GitHub repository and start helping us improve the tool.
You can fork the [GitHub repository](https://github.com/numediart/ISGT) and start helping us improve the tool.

You can find the complete technical documentation [here](./Doc/doc-menu.md).
You can find the technical documentation [here](./Doc/doc-menu.md).

0 comments on commit 9cae4a3

Please sign in to comment.