I've been working on in editor paint tools and I've mostly got it working but as you can see from the screenshot edges are currently a issue.
Attachment:
vtpainttools.png [ 255.33 KB | Viewed 256 times ]
Currently I'm tracing a unprojected ray against the world to figure out a) what vt area we hit and b) that point needs to get converted back into 2d coords so we can figure out were to paint. To do the latter I'm using a heavily modified version of idRenderWorldLocal::GuiTrace. The problem is this function is very inacurate on non flat surfaces. My modified function below:
Code:
/*
================
VTTrace
================
*/
vtPoint_t idRenderWorldLocal::VTTrace( int vtAreaId, const idVec3 start, const idVec3 end ) const {
srfTriangles_t *tri;
vtPoint_t pt;
localTrace_t local;
const modelSurface_t *vtsurf = NULL;
memset( &pt, 0, sizeof(vtPoint_t));
if(vtAreaId == -1) {
common->Warning("VTTrace: Can't trace against non vt areas.\n");
return pt;
}
for(int i = 0; i < localModels.Num(); i++)
{
idRenderModel *model = localModels[i];
//common->Printf("Generating Collision for %s - %d collision models\n", model->Name(), model->NumSurfaces() );
for(int s = 0; s < model->NumSurfaces(); s++)
{
const modelSurface_t *surf = model->Surface( s );
if(surf->geometry->vt_AreaID == vtAreaId) {
vtsurf = surf;
break;
}
}
if(vtsurf != NULL)
break;
}
if(vtsurf == NULL) {
common->Warning("VTTrace: VTArea %d is invalid!\n", vtAreaId);
return pt;
}
tri = vtsurf->geometry;
local = R_LocalTrace( start, end, 0.0f, tri );
if ( local.fraction < 1.0 ) {
idVec3 origin, axis[3];
idVec3 cursor;
float axisLen[2];
R_SurfaceToTextureAxis( tri, origin, axis, &local.indexes[0], &local.plane );
cursor = local.point - origin;
int closestIndex = 0;
if(local.d[0] > local.d[1] && local.d[0] > local.d[2])
{
closestIndex = local.indexes[0];
}
else if(local.d[1] > local.d[0] && local.d[1] > local.d[2])
{
closestIndex = local.indexes[1];
}
else if(local.d[2] > local.d[1] && local.d[2] > local.d[0])
{
closestIndex = local.indexes[2];
}
cursor = local.point - tri->verts[closestIndex].xyz;
axisLen[0] = axis[0].Length();
axisLen[1] = axis[1].Length();
pt.x = ( cursor * axis[0] ) / ( axisLen[0] * axisLen[0] );
pt.y = ( cursor * axis[1] ) / ( axisLen[1] * axisLen[1] );
pt.x += tri->verts[closestIndex].st.x;
pt.y += tri->verts[closestIndex].st.y;
return pt;
}
common->Warning("VTTrace Failed.\n");
return pt;
}
Basically what makes this function more accurate is I interporlate the position from the nearest point that got hit and extrapolate the final position that way. And it works 90% of the time but its still not as acurate as I need it to be. Has anyone been working on something like this that can provide some insite on what I'm doing wrong?