//======================================================================================== // geCamera_ScreenPointToWorld //======================================================================================== GENESISAPI void GENESISCC geCamera_ScreenPointToWorld ( const geCamera *Camera, int32 ScreenX, int32 ScreenY, geVec3d *Vector) // Takes a screen X and Y pair, and a camera and generates a vector pointing // in the direction from the camera position to the screen point. { geVec3d In,Left,Up; geVec3d ScaledIn,ScaledLeft,ScaledUp ; geFloat XCenter ; geFloat YCenter ; geFloat Scale ; const geXForm3d *pM; pM = &(Camera->TransposeXForm); XCenter = Camera->XCenter ; YCenter = Camera->YCenter ; Scale = Camera->Scale ; geXForm3d_GetIn( pM, &In ) ; geXForm3d_GetLeft( pM, &Left ) ; geXForm3d_GetUp( pM, &Up ) ; geVec3d_Scale(&In, Scale, &ScaledIn); geVec3d_Scale(&Left, XCenter - ((geFloat)ScreenX), &ScaledLeft ); geVec3d_Scale(&Up, YCenter - ((geFloat)ScreenY), &ScaledUp ); geVec3d_Copy(&ScaledIn, Vector); geVec3d_Add(Vector, &ScaledLeft, Vector ); geVec3d_Add(Vector, &ScaledUp, Vector ); geVec3d_Normalize(Vector); }
//===================================================================================== // RenderTexturedPoint //===================================================================================== static geBoolean RenderTexturedPoint(DRV_Driver *RDriver, gePoly *Poly, Frustum_Info *FInfo, geCamera *Camera) { assert(geWorld_PolyIsValid(Poly)); if (MirrorRecursion > 0) { GE_LVertex *pVerts, Save; geVec3d Up, Left, Start; geFloat Scale, XScale, YScale; const geXForm3d *MXForm; pVerts = Poly->Verts; Poly->NumVerts = 4; Start.X = pVerts[0].X; Start.Y = pVerts[0].Y; Start.Z = pVerts[0].Z; Save = pVerts[1] = pVerts[2] = pVerts[3] = pVerts[0]; MXForm = geCamera_GetWorldSpaceXForm(Camera); geXForm3d_GetLeft(MXForm, &Left); geXForm3d_GetUp(MXForm, &Up); Scale = Poly->Scale * 0.5f; XScale = (geFloat)geBitmap_Width(Poly->Bitmap) * Scale; YScale = (geFloat)geBitmap_Height(Poly->Bitmap) * Scale; geVec3d_Scale(&Left, XScale, &Left); geVec3d_Scale(&Up, YScale, &Up); pVerts->X = Start.X - Left.X + Up.X; pVerts->Y = Start.Y - Left.Y + Up.Y; pVerts->Z = Start.Z - Left.Z + Up.Z; pVerts->u = 0.0f; pVerts->v = 0.0f; pVerts++; pVerts->X = Start.X + Left.X + Up.X; pVerts->Y = Start.Y + Left.Y + Up.Y; pVerts->Z = Start.Z + Left.Z + Up.Z; pVerts->u = 1.0f; pVerts->v = 0.0f; pVerts++; pVerts->X = Start.X + Left.X - Up.X; pVerts->Y = Start.Y + Left.Y - Up.Y; pVerts->Z = Start.Z + Left.Z - Up.Z; pVerts->u = 1.0f; pVerts->v = 1.0f; pVerts++; pVerts->X = Start.X - Left.X - Up.X; pVerts->Y = Start.Y - Left.Y - Up.Y; pVerts->Z = Start.Z - Left.Z - Up.Z; pVerts->u = 1.0f; pVerts->v = 0.0f; RenderTexturedPoly(RDriver, Poly, FInfo, Camera); Poly->NumVerts = 1; // Restore the poly Poly->Verts[0] = Save; } else { //GFX_Plane *Planes; geVec3d Src, Dest; GE_LVertex *pVerts; DRV_TLVertex ScreenPnts[4]; geBitmap *Bitmap; geFloat Sx, Sy, z, UVAdd, Width, Height; geFloat Left, Right, Top, Bottom; geFloat Scale; uint32 RenderFlags; int32 i; assert(Poly != NULL); assert(Camera != NULL); pVerts = &Poly->Verts[0]; // Xform the point Src.X = pVerts->X; Src.Y = pVerts->Y; Src.Z = pVerts->Z; geCamera_Transform(Camera,&Src,&Dest); geCamera_Project(Camera, &Dest, &Src); for (i=0; i<4; i++) { ScreenPnts[i].x = Src.X; ScreenPnts[i].y = Src.Y; ScreenPnts[i].z = Src.Z; ScreenPnts[i].r = pVerts->r; ScreenPnts[i].g = pVerts->g; ScreenPnts[i].b = pVerts->b; ScreenPnts[i].a = pVerts->a; } z = -Dest.Z; if (z < 1) return GE_TRUE; { geRect Rect; geCamera_GetClippingRect(Camera,&Rect); Left = (geFloat)Rect.Left; Right = (geFloat)Rect.Right+1.0f; Top = (geFloat)Rect.Top; Bottom = (geFloat)Rect.Bottom+1.0f; } Scale = ((geCamera_GetScale(Camera) / z) * Poly->Scale); Bitmap = Poly->Bitmap; Width = (geFloat)geBitmap_Width(Bitmap) * Scale; Height = (geFloat)geBitmap_Height(Bitmap) * Scale; Sx = Width * 0.5f; Sy = Height * 0.5f; // Build the screen poly from the point ScreenPnts[0].x -= Sx; ScreenPnts[0].y -= Sy; ScreenPnts[1].x += Sx; ScreenPnts[1].y -= Sy; ScreenPnts[2].x += Sx; ScreenPnts[2].y += Sy; ScreenPnts[3].x -= Sx; ScreenPnts[3].y += Sy; ScreenPnts[0].u = 0.0f + pVerts->u; ScreenPnts[0].v = 0.0f + pVerts->v; ScreenPnts[1].u = 1.0f + pVerts->u; ScreenPnts[1].v = 0.0f + pVerts->v; ScreenPnts[2].u = 1.0f + pVerts->u; ScreenPnts[2].v = 1.0f + pVerts->v; ScreenPnts[3].u = 0.0f + pVerts->u; ScreenPnts[3].v = 1.0f + pVerts->v; // Now, clip it against the 2d camera viewport if (ScreenPnts[0].x < Left) { if (ScreenPnts[1].x <= Left) return GE_TRUE; UVAdd = (Left-ScreenPnts[0].x) / Width; Width -= Left-ScreenPnts[0].x; ScreenPnts[0].u += UVAdd; ScreenPnts[3].u += UVAdd; ScreenPnts[0].x = Left; ScreenPnts[3].x = Left; } if (ScreenPnts[0].y < Top) { if (ScreenPnts[2].y <= Top) return GE_TRUE; UVAdd = (Top-ScreenPnts[0].y) / Height; Height -= (Top-ScreenPnts[0].y); ScreenPnts[0].v += UVAdd; ScreenPnts[1].v += UVAdd; ScreenPnts[0].y = Top; ScreenPnts[1].y = Top; } if (ScreenPnts[1].x >= Right) { if (ScreenPnts[0].x >= Right) return GE_TRUE; UVAdd = (ScreenPnts[1].x-Right) / Width; Width -= (ScreenPnts[1].x-Right); ScreenPnts[1].u -= UVAdd; ScreenPnts[2].u -= UVAdd; ScreenPnts[1].x = Right-1; ScreenPnts[2].x = Right-1; } if (ScreenPnts[2].y >= Bottom) { if (ScreenPnts[0].y >= Bottom) return GE_TRUE; UVAdd = (ScreenPnts[2].y-Bottom) / Height; Height -= (ScreenPnts[2].x-Bottom); ScreenPnts[2].v -= UVAdd; ScreenPnts[3].v -= UVAdd; ScreenPnts[2].y = Bottom-1; ScreenPnts[3].y = Bottom-1; } // Lastly, render it... ScreenPnts[0].a = pVerts->a; // Fixed bug where i fogot to set RGB's... ScreenPnts[0].r = pVerts->r; ScreenPnts[0].g = pVerts->g; ScreenPnts[0].b = pVerts->b; if (Poly->RenderFlags & GE_RENDER_DO_NOT_OCCLUDE_OTHERS) RenderFlags = DRV_RENDER_NO_ZWRITE; else RenderFlags = 0; if (Poly->RenderFlags & GE_RENDER_DO_NOT_OCCLUDE_SELF) RenderFlags |= DRV_RENDER_NO_ZMASK; if (pVerts->a != 255.0f) RenderFlags |= DRV_RENDER_ALPHA; /* 01/30/2003 Wendell Buckner Driver render flush is probably causing a slow down! */ if (Poly->RenderFlags & GE_RENDER_DEPTH_SORT_BF) RenderFlags |= DRV_RENDER_FLUSH; if (Poly->RenderFlags & GE_RENDER_CLAMP_UV) RenderFlags |= DRV_RENDER_CLAMP_UV; if (Poly->RenderFlags & GE_RENDER_NO_FOG) // skybox fog RenderFlags |= DRV_RENDER_POLY_NO_FOG; assert(geWorld_HasBitmap(gWorld, Bitmap)); assert(geBitmap_GetTHandle(Bitmap)); /* 08/08/2004 Wendell Buckner BUG FIX: Allways call geBitmap_SetRenderFlags() before calling a textured rendering function(for embm, dot3, & etc...). */ geBitmap_SetRenderFlags(Bitmap, &RenderFlags); RDriver->RenderMiscTexturePoly((DRV_TLVertex*)ScreenPnts, 4, geBitmap_GetTHandle(Bitmap), RenderFlags); } return GE_TRUE; }