fallout2-ce/src/geometry.cc

186 lines
4.9 KiB
C++
Raw Normal View History

2022-05-19 01:51:26 -07:00
#include "geometry.h"
2022-09-15 02:38:23 -07:00
#include <stdlib.h>
2022-05-19 01:51:26 -07:00
2022-05-21 08:22:03 -07:00
#include <algorithm>
2022-09-15 02:38:23 -07:00
#include "memory.h"
2022-05-19 01:51:26 -07:00
// 0x51DEF4
2022-06-19 03:20:13 -07:00
static RectListNode* _rectList = NULL;
2022-05-19 01:51:26 -07:00
// 0x4C6900
void _GNW_rect_exit()
{
while (_rectList != NULL) {
RectListNode* next = _rectList->next;
internal_free(_rectList);
_rectList = next;
}
}
// 0x4C6924
void _rect_clip_list(RectListNode** rectListNodePtr, Rect* rect)
{
Rect v1;
rectCopy(&v1, rect);
// NOTE: Original code is slightly different.
while (*rectListNodePtr != NULL) {
RectListNode* rectListNode = *rectListNodePtr;
if (v1.right >= rectListNode->rect.left
&& v1.bottom >= rectListNode->rect.top
&& v1.left <= rectListNode->rect.right
&& v1.top <= rectListNode->rect.bottom) {
Rect v2;
rectCopy(&v2, &(rectListNode->rect));
*rectListNodePtr = rectListNode->next;
rectListNode->next = _rectList;
_rectList = rectListNode;
if (v2.top < v1.top) {
RectListNode* newRectListNode = _rect_malloc();
if (newRectListNode == NULL) {
return;
}
rectCopy(&(newRectListNode->rect), &v2);
newRectListNode->rect.bottom = v1.top - 1;
newRectListNode->next = *rectListNodePtr;
*rectListNodePtr = newRectListNode;
rectListNodePtr = &(newRectListNode->next);
v2.top = v1.top;
}
if (v2.bottom > v1.bottom) {
RectListNode* newRectListNode = _rect_malloc();
if (newRectListNode == NULL) {
return;
}
rectCopy(&(newRectListNode->rect), &v2);
newRectListNode->rect.top = v1.bottom + 1;
newRectListNode->next = *rectListNodePtr;
*rectListNodePtr = newRectListNode;
rectListNodePtr = &(newRectListNode->next);
v2.bottom = v1.bottom;
}
if (v2.left < v1.left) {
RectListNode* newRectListNode = _rect_malloc();
if (newRectListNode == NULL) {
return;
}
rectCopy(&(newRectListNode->rect), &v2);
newRectListNode->rect.right = v1.left - 1;
newRectListNode->next = *rectListNodePtr;
*rectListNodePtr = newRectListNode;
rectListNodePtr = &(newRectListNode->next);
}
if (v2.right > v1.right) {
RectListNode* newRectListNode = _rect_malloc();
if (newRectListNode == NULL) {
return;
}
rectCopy(&(newRectListNode->rect), &v2);
newRectListNode->rect.left = v1.right + 1;
newRectListNode->next = *rectListNodePtr;
*rectListNodePtr = newRectListNode;
rectListNodePtr = &(newRectListNode->next);
}
} else {
rectListNodePtr = &(rectListNode->next);
}
}
}
// 0x4C6BB8
RectListNode* _rect_malloc()
{
if (_rectList == NULL) {
for (int index = 0; index < 10; index++) {
2022-05-21 08:22:03 -07:00
RectListNode* rectListNode = (RectListNode*)internal_malloc(sizeof(*rectListNode));
2022-05-19 01:51:26 -07:00
if (rectListNode == NULL) {
break;
}
// NOTE: Uninline.
_rect_free(rectListNode);
}
}
if (_rectList == NULL) {
return NULL;
}
RectListNode* rectListNode = _rectList;
_rectList = _rectList->next;
return rectListNode;
}
// 0x4C6C04
void _rect_free(RectListNode* rectListNode)
{
rectListNode->next = _rectList;
_rectList = rectListNode;
}
// Calculates a union of two source rectangles and places it into result
// rectangle.
//
// 0x4C6C18
void rectUnion(const Rect* s1, const Rect* s2, Rect* r)
{
2022-05-21 08:22:03 -07:00
r->left = std::min(s1->left, s2->left);
r->top = std::min(s1->top, s2->top);
r->right = std::max(s1->right, s2->right);
r->bottom = std::max(s1->bottom, s2->bottom);
2022-05-19 01:51:26 -07:00
}
// Calculates intersection of two source rectangles and places it into third
// rectangle and returns 0. If two source rectangles do not have intersection
// it returns -1 and resulting rectangle is a copy of s1.
//
// 0x4C6C68
int rectIntersection(const Rect* s1, const Rect* s2, Rect* r)
{
r->left = s1->left;
r->top = s1->top;
r->right = s1->right;
r->bottom = s1->bottom;
if (s1->left <= s2->right && s2->left <= s1->right && s2->bottom >= s1->top && s2->top <= s1->bottom) {
if (s2->left > s1->left) {
r->left = s2->left;
}
if (s2->right < s1->right) {
r->right = s2->right;
}
if (s2->top > s1->top) {
r->top = s2->top;
}
if (s2->bottom < s1->bottom) {
r->bottom = s2->bottom;
}
return 0;
}
return -1;
}