mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-12 08:11:10 +02:00
Selection visualization is now fixed.
This commit is contained in:
@@ -48,7 +48,7 @@ static char THIS_FILE[] = __FILE__;
|
||||
extern void DrawPathLines();
|
||||
|
||||
extern qertrace_t Test_Ray(const idVec3& origin, const idVec3& dir, int flags);
|
||||
extern brush_t *Brush_CreateFaceExtrusion(brush_t *sourceBrush, face_t *sourceFace, float distance);
|
||||
extern brush_t* Brush_CreateFaceExtrusion(brush_t* sourceBrush, face_t* sourceFace, float distance);
|
||||
extern void Select_ShiftTexture(float x, float y);
|
||||
extern void Select_ScaleTexture(float x, float y);
|
||||
extern void Select_RotateTexture(float amt, bool absolute);
|
||||
@@ -1609,11 +1609,12 @@ from the selected face and linked to the same entity as the source brush.
|
||||
struct camFaceExtrudeState_t {
|
||||
bool active;
|
||||
bool moved;
|
||||
CCamWnd* cam;
|
||||
brush_t* sourceBrush;
|
||||
face_t* sourceFace;
|
||||
idWinding* sourceWinding;
|
||||
CCamWnd* cam;
|
||||
brush_t* sourceBrush;
|
||||
face_t* sourceFace;
|
||||
idWinding* sourceWinding;
|
||||
idVec3 normal;
|
||||
idVec3 hitPoint;
|
||||
CPoint startPoint;
|
||||
float distance;
|
||||
};
|
||||
@@ -1717,6 +1718,7 @@ static bool CamWnd_FaceExtrudeBegin(CCamWnd* cam, const CPoint& point) {
|
||||
s_faceExtrudeState.sourceFace = trace.face;
|
||||
s_faceExtrudeState.sourceWinding = trace.face->face_winding->Copy();
|
||||
s_faceExtrudeState.normal = normal;
|
||||
s_faceExtrudeState.hitPoint = cam->Camera().origin + dir * trace.dist;
|
||||
s_faceExtrudeState.startPoint = point;
|
||||
s_faceExtrudeState.distance = 0.0f;
|
||||
|
||||
@@ -1727,17 +1729,53 @@ static bool CamWnd_FaceExtrudeBegin(CCamWnd* cam, const CPoint& point) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool CamWnd_FaceExtrudeDistanceFromRay(CCamWnd* cam, const CPoint& point, float& distance) {
|
||||
idVec3 rayDir;
|
||||
CamWnd_FaceExtrudeBuildRay(cam, point, rayDir);
|
||||
|
||||
const idVec3 rayOrigin = cam->Camera().origin;
|
||||
const idVec3 lineOrigin = s_faceExtrudeState.hitPoint;
|
||||
const idVec3 lineDir = s_faceExtrudeState.normal;
|
||||
|
||||
// Find the closest point between the current mouse ray and the extrusion
|
||||
// normal through the original hit point. This makes the drag distance match
|
||||
// the world-space preview instead of treating one screen pixel as one unit.
|
||||
const float b = DotProduct(rayDir, lineDir);
|
||||
const float denom = 1.0f - b * b;
|
||||
if (denom < 0.0001f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
idVec3 w = rayOrigin - lineOrigin;
|
||||
const float d = DotProduct(rayDir, w);
|
||||
const float e = DotProduct(lineDir, w);
|
||||
const float t = (e - b * d) / denom;
|
||||
const float rayT = b * t - d;
|
||||
|
||||
if (rayT < 0.0f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
distance = t;
|
||||
return true;
|
||||
}
|
||||
|
||||
static float CamWnd_FaceExtrudeMouseDistance(CCamWnd* cam, const CPoint& point) {
|
||||
float distance = 0.0f;
|
||||
if (CamWnd_FaceExtrudeDistanceFromRay(cam, point, distance)) {
|
||||
return CamWnd_FaceExtrudeSnapDistance(distance);
|
||||
}
|
||||
|
||||
const int dx = point.x - s_faceExtrudeState.startPoint.x;
|
||||
const int dy = point.y - s_faceExtrudeState.startPoint.y;
|
||||
|
||||
camera_t& camera = cam->Camera();
|
||||
idVec3 screenMove = camera.vright * (float)dx - camera.vup * (float)dy;
|
||||
float distance = DotProduct(screenMove, s_faceExtrudeState.normal);
|
||||
distance = DotProduct(screenMove, s_faceExtrudeState.normal);
|
||||
|
||||
// When the selected face is nearly screen-facing, projection onto the normal
|
||||
// is too small to be useful. In that case use vertical mouse motion, with
|
||||
// the sign chosen so dragging up extrudes toward the camera-facing normal.
|
||||
// When the normal projects poorly onto the screen, fall back to vertical
|
||||
// mouse motion, with the sign chosen so dragging up extrudes toward the
|
||||
// camera-facing normal.
|
||||
float verticalDistance = (float)-dy;
|
||||
if (DotProduct(camera.vpn, s_faceExtrudeState.normal) > 0.0f) {
|
||||
verticalDistance = -verticalDistance;
|
||||
@@ -1795,79 +1833,104 @@ static void CamWnd_FaceExtrudeEnd(CCamWnd* cam, bool commit) {
|
||||
Sys_UpdateWindows(W_ALL);
|
||||
}
|
||||
|
||||
static void CamWnd_DrawFaceWindingFilled(face_t* face) {
|
||||
if (face == NULL || face->face_winding == NULL || face->face_winding->GetNumPoints() < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
for (int i = 0; i < face->face_winding->GetNumPoints(); i++) {
|
||||
glVertex3fv((*face->face_winding)[i].ToFloatPtr());
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static void CamWnd_DrawFaceWindingOutline(face_t* face) {
|
||||
if (face == NULL || face->face_winding == NULL || face->face_winding->GetNumPoints() < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
glBegin(GL_LINE_LOOP);
|
||||
for (int i = 0; i < face->face_winding->GetNumPoints(); i++) {
|
||||
glVertex3fv((*face->face_winding)[i].ToFloatPtr());
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static void CamWnd_DrawTransparentFace(face_t* face, float r, float g, float b, float a) {
|
||||
if (face == NULL || face->face_winding == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
glPushAttrib(GL_CURRENT_BIT);
|
||||
globalImages->BindNull();
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glColor4f(r, g, b, a);
|
||||
CamWnd_DrawFaceWindingFilled(face);
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
static void CamWnd_FaceExtrudeDrawPreview(CCamWnd* cam) {
|
||||
if (!CamWnd_FaceExtrudeIsActive(cam) || s_faceExtrudeState.sourceWinding == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Always tint the source side while it is selected for extrusion, even before
|
||||
// the mouse has moved far enough to create a non-zero snapped preview.
|
||||
CamWnd_DrawTransparentFace(s_faceExtrudeState.sourceFace, 1.0f, 0.0f, 0.0f, 0.25f);
|
||||
|
||||
if (idMath::Fabs(s_faceExtrudeState.distance) < CAMWND_FACE_EXTRUDE_EPSILON) {
|
||||
return;
|
||||
}
|
||||
|
||||
idWinding* w = s_faceExtrudeState.sourceWinding;
|
||||
const int numPoints = w->GetNumPoints();
|
||||
if (numPoints < 3) {
|
||||
brush_t* previewBrush = Brush_CreateFaceExtrusion(
|
||||
s_faceExtrudeState.sourceBrush,
|
||||
s_faceExtrudeState.sourceFace,
|
||||
s_faceExtrudeState.distance);
|
||||
if (previewBrush == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
idVec3 offset = s_faceExtrudeState.normal * s_faceExtrudeState.distance;
|
||||
Brush_Build(previewBrush, true, false, false, false);
|
||||
Brush_RemoveEmptyFaces(previewBrush);
|
||||
if (previewBrush->brush_faces == NULL) {
|
||||
Brush_Free(previewBrush);
|
||||
return;
|
||||
}
|
||||
|
||||
glPushAttrib(GL_CURRENT_BIT);
|
||||
globalImages->BindNull();
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_BLEND);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glLineWidth(2.0f);
|
||||
glColor3f(0.1f, 0.9f, 1.0f);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
for (int i = 0; i < numPoints; i++) {
|
||||
const int j = (i + 1) % numPoints;
|
||||
idVec3 a = (*w)[i].ToVec3();
|
||||
idVec3 b = (*w)[j].ToVec3();
|
||||
idVec3 a2 = a + offset;
|
||||
idVec3 b2 = b + offset;
|
||||
|
||||
glVertex3fv(a.ToFloatPtr());
|
||||
glVertex3fv(b.ToFloatPtr());
|
||||
glVertex3fv(a2.ToFloatPtr());
|
||||
glVertex3fv(b2.ToFloatPtr());
|
||||
glVertex3fv(a.ToFloatPtr());
|
||||
glVertex3fv(a2.ToFloatPtr());
|
||||
for (face_t* face = previewBrush->brush_faces; face; face = face->next) {
|
||||
CamWnd_DrawFaceWindingOutline(face);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glColor4f(0.1f, 0.9f, 1.0f, 0.18f);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
for (int i = 0; i < numPoints; i++) {
|
||||
idVec3 p = (*w)[i].ToVec3() + offset;
|
||||
glVertex3fv(p.ToFloatPtr());
|
||||
for (face_t* face = previewBrush->brush_faces; face; face = face->next) {
|
||||
CamWnd_DrawFaceWindingFilled(face);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
for (int i = 0; i < numPoints; i++) {
|
||||
const int j = (i + 1) % numPoints;
|
||||
idVec3 a = (*w)[i].ToVec3();
|
||||
idVec3 b = (*w)[j].ToVec3();
|
||||
idVec3 a2 = a + offset;
|
||||
idVec3 b2 = b + offset;
|
||||
|
||||
glVertex3fv(a.ToFloatPtr());
|
||||
glVertex3fv(b.ToFloatPtr());
|
||||
glVertex3fv(b2.ToFloatPtr());
|
||||
glVertex3fv(a2.ToFloatPtr());
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glPopAttrib();
|
||||
Brush_Free(previewBrush);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static COLORREF CamWnd_LerpColor(COLORREF a, COLORREF b, float t) {
|
||||
const int ar = GetRValue(a);
|
||||
const int ag = GetGValue(a);
|
||||
@@ -2896,6 +2959,56 @@ void setGLMode(int mode) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool CamWnd_FaceHasAllPlanePointsSelected(face_t* face) {
|
||||
if (face == NULL || face->face_winding == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (PointInMoveList(&face->planepts[i]) < 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void CamWnd_DrawMoveSelectedBrushSidesForList(CCamWnd* cam, brush_t* list) {
|
||||
if (list == NULL || list->next == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (brush_t* brush = list->next; brush != list; brush = brush->next) {
|
||||
if (CamWnd_MenuFilterBrush(cam, brush)) {
|
||||
continue;
|
||||
}
|
||||
if (brush->pPatch || brush->modelHandle > 0 || brush->entityModel) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (face_t* face = brush->brush_faces; face; face = face->next) {
|
||||
if (CamWnd_FaceHasAllPlanePointsSelected(face)) {
|
||||
CamWnd_DrawFaceWindingFilled(face);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CamWnd_DrawMoveSelectedBrushSides(CCamWnd* cam) {
|
||||
glPushAttrib(GL_CURRENT_BIT);
|
||||
globalImages->BindNull();
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glColor4f(1.0f, 0.0f, 0.0f, 0.25f);
|
||||
|
||||
CamWnd_DrawMoveSelectedBrushSidesForList(cam, &active_brushes);
|
||||
CamWnd_DrawMoveSelectedBrushSidesForList(cam, &selected_brushes);
|
||||
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
|
||||
extern void glLabeledPoint(idVec4& color, idVec3& point, float size, const char* label);
|
||||
void DrawAxial(face_t* selFace) {
|
||||
@@ -3115,19 +3228,19 @@ void CCamWnd::Cam_Draw() {
|
||||
}
|
||||
|
||||
// non-zbuffered outline
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
//glDisable(GL_BLEND);
|
||||
//glDisable(GL_DEPTH_TEST);
|
||||
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
|
||||
if (renderMode) {
|
||||
glColor3f(1, 0, 0);
|
||||
glColor4f(1.0f, 0.0f, 0.0f, 0.25f);
|
||||
for (int i = 0; i < nCount; i++) {
|
||||
face_t* selFace = reinterpret_cast <face_t*>(g_ptrSelectedFaces.GetAt(i));
|
||||
Face_Draw(selFace);
|
||||
}
|
||||
}
|
||||
|
||||
glColor3f(1, 1, 1);
|
||||
glColor4f(1.0f, 0.0f, 0.0f, 0.25f);
|
||||
for (brush = pList->next; brush != pList; brush = brush->next) {
|
||||
if (CamWnd_MenuFilterBrush(this, brush)) {
|
||||
continue;
|
||||
@@ -3141,6 +3254,7 @@ void CCamWnd::Cam_Draw() {
|
||||
}
|
||||
}
|
||||
|
||||
CamWnd_DrawMoveSelectedBrushSides(this);
|
||||
CamWnd_FaceExtrudeDrawPreview(this);
|
||||
|
||||
// edge / vertex flags
|
||||
|
||||
Reference in New Issue
Block a user