// Neutral case: returns whether vertex-source data was used (present in animated models) bool Model3D::FindPositions_Neutral(bool UseModelTransform) { // Positions already there if (VtxSrcIndices.empty()) { return false; } // Straight copy of the vertices: size_t NumVertices = VtxSrcIndices.size(); Positions.resize(3*NumVertices); GLfloat *PP = PosBase(); GLushort *IP = VtxSIBase(); size_t NumVtxSources = VtxSources.size(); if (UseModelTransform) { for (size_t k=0; k<NumVertices; k++, IP++, PP+=3) { size_t VSIndex = *IP; if (VSIndex >= 0 && VSIndex < NumVtxSources) { Model3D_VertexSource& VS = VtxSources[VSIndex]; TransformPoint(PP,VS.Position,TransformPos); } else { GLfloat VP[3] = {0,0,0}; TransformPoint(PP,VP,TransformPos); } } } else { for (size_t k=0; k<NumVertices; k++, IP++) { size_t VSIndex = *IP; if (VSIndex >= 0 && VSIndex < NumVtxSources) { Model3D_VertexSource& VS = VtxSources[VSIndex]; GLfloat *VP = VS.Position; *(PP++) = *(VP++); *(PP++) = *(VP++); *(PP++) = *(VP++); } else { *(PP++) = 0; *(PP++) = 0; *(PP++) = 0; } } } // Copy in the normals Normals.resize(NormSources.size()); if (UseModelTransform) { GLfloat *NormPtr = NormBase(); GLfloat *NormBasePtr = NormSrcBase(); size_t NumNorms = NormSources.size()/3; for (size_t k=0; k<NumNorms; k++, NormPtr+=3, NormBasePtr+=3) { TransformVector(NormPtr, NormBasePtr, TransformNorm); } } else { objlist_copy(NormBase(),NormSrcBase(),NormSources.size()); } return true; }
/* ================ R_EmitEdge ================ */ void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) { edge_t *edge, *pcheck; int u_check, v, v2, ceilv0, side; float u, u_step, *world, scale, lzi0, u0, v0; vec3_t local, transformed; if (r_lastvertvalid) { u0 = r_u1; v0 = r_v1; lzi0 = r_lzi1; ceilv0 = r_ceilv1; } else { world = &pv0->position[0]; // transform and project VectorSubtract (world, modelorg, local); TransformVector (local, transformed); if (transformed[2] < NEAR_CLIP) transformed[2] = NEAR_CLIP; lzi0 = 1.0 / transformed[2]; // FIXME: build x/yscale into transform? scale = xscale * lzi0; u0 = (xcenter + scale * transformed[0]); u0 = bound(r_refdef.fvrectx_adj, u0, r_refdef.fvrectright_adj); scale = yscale * lzi0; v0 = (ycenter - scale * transformed[1]); v0 = bound(r_refdef.fvrecty_adj, v0, r_refdef.fvrectbottom_adj); ceilv0 = (int) ceil(v0); } world = &pv1->position[0]; // transform and project VectorSubtract (world, modelorg, local); TransformVector (local, transformed); if (transformed[2] < NEAR_CLIP) transformed[2] = NEAR_CLIP; r_lzi1 = 1.0 / transformed[2]; scale = xscale * r_lzi1; r_u1 = (xcenter + scale * transformed[0]); r_u1 = bound(r_refdef.fvrectx_adj, r_u1, r_refdef.fvrectright_adj); scale = yscale * r_lzi1; r_v1 = (ycenter - scale * transformed[1]); r_v1 = bound(r_refdef.fvrecty_adj, r_v1, r_refdef.fvrectbottom_adj); if (r_lzi1 > lzi0) lzi0 = r_lzi1; if (lzi0 > r_nearzi) // for mipmap finding r_nearzi = lzi0; // for right edges, all we want is the effect on 1/z if (r_nearzionly) return; r_emitted = 1; r_ceilv1 = (int) ceil(r_v1); // create the edge if (ceilv0 == r_ceilv1) { // we cache unclipped horizontal edges as fully clipped if (cacheoffset != 0x7FFFFFFF) cacheoffset = FULLY_CLIPPED_CACHED |(r_framecount & FRAMECOUNT_MASK); return; // horizontal edge } side = ceilv0 > r_ceilv1; edge = edge_p++; edge->owner = r_pedge; edge->nearzi = lzi0; if (side == 0) { // trailing edge (go from p1 to p2) v = ceilv0; v2 = r_ceilv1 - 1; edge->surfs[0] = surface_p - surfaces; edge->surfs[1] = 0; u_step = ((r_u1 - u0) / (r_v1 - v0)); u = u0 + ((float)v - v0) * u_step; } else { // leading edge (go from p2 to p1) v2 = ceilv0 - 1; v = r_ceilv1; edge->surfs[0] = 0; edge->surfs[1] = surface_p - surfaces; u_step = ((u0 - r_u1) / (v0 - r_v1)); u = r_u1 + ((float)v - r_v1) * u_step; } edge->u_step = u_step*0x100000; edge->u = u*0x100000 + 0xFFFFF; // we need to do this to avoid stepping off the edges if a very nearly horizontal edge is less // than epsilon above a scan, and numeric error causes it to incorrectly extend to the scan, // and the extension of the line goes off the edge of the screen // FIXME: is this actually needed? if (edge->u < r_refdef.vrect_x_adj_shift20) edge->u = r_refdef.vrect_x_adj_shift20; if (edge->u > r_refdef.vrectright_adj_shift20) edge->u = r_refdef.vrectright_adj_shift20; // sort the edge in normally u_check = edge->u; if (edge->surfs[0]) u_check++; // sort trailers after leaders if (!newedges[v] || newedges[v]->u >= u_check) { edge->next = newedges[v]; newedges[v] = edge; } else { pcheck = newedges[v]; while (pcheck->next && pcheck->next->u < u_check) pcheck = pcheck->next; edge->next = pcheck->next; pcheck->next = edge; } edge->nextremove = removeedges[v2]; removeedges[v2] = edge; }
void R_SetupAndDrawSprite (void) { int i, nump; float dot, scale, *pv; vec5_t *pverts; vec3_t left, up, right, down, transformed, local; emitpoint_t outverts[MAXWORKINGVERTS + 1], *pout; dot = DotProduct (r_spritedesc.vpn, modelorg); // backface cull if (dot >= 0) return; // build the sprite poster in worldspace VectorScale (r_spritedesc.vright, r_spritedesc.pspriteframe->right, right); VectorScale (r_spritedesc.vup, r_spritedesc.pspriteframe->up, up); VectorScale (r_spritedesc.vright, r_spritedesc.pspriteframe->left, left); VectorScale (r_spritedesc.vup, r_spritedesc.pspriteframe->down, down); pverts = clip_verts[0]; pverts[0][0] = r_entorigin[0] + up[0] + left[0]; pverts[0][1] = r_entorigin[1] + up[1] + left[1]; pverts[0][2] = r_entorigin[2] + up[2] + left[2]; pverts[0][3] = 0; pverts[0][4] = 0; pverts[1][0] = r_entorigin[0] + up[0] + right[0]; pverts[1][1] = r_entorigin[1] + up[1] + right[1]; pverts[1][2] = r_entorigin[2] + up[2] + right[2]; pverts[1][3] = sprite_width; pverts[1][4] = 0; pverts[2][0] = r_entorigin[0] + down[0] + right[0]; pverts[2][1] = r_entorigin[1] + down[1] + right[1]; pverts[2][2] = r_entorigin[2] + down[2] + right[2]; pverts[2][3] = sprite_width; pverts[2][4] = sprite_height; pverts[3][0] = r_entorigin[0] + down[0] + left[0]; pverts[3][1] = r_entorigin[1] + down[1] + left[1]; pverts[3][2] = r_entorigin[2] + down[2] + left[2]; pverts[3][3] = 0; pverts[3][4] = sprite_height; // clip to the frustum in worldspace nump = 4; clip_current = 0; for (i = 0; i < 4; i++) { nump = R_ClipSpriteFace (nump, &view_clipplanes[i]); if (nump < 3) return; if (nump >= MAXWORKINGVERTS) Host_Error ("R_SetupAndDrawSprite: too many points"); } // transform vertices into viewspace and project pv = &clip_verts[clip_current][0][0]; r_spritedesc.nearzi = -999999; for (i = 0; i < nump; i++) { VectorSubtract (pv, r_origin, local); TransformVector (local, transformed); if (transformed[2] < NEAR_CLIP) transformed[2] = NEAR_CLIP; pout = &outverts[i]; pout->zi = 1.0 / transformed[2]; if (pout->zi > r_spritedesc.nearzi) r_spritedesc.nearzi = pout->zi; pout->s = pv[3]; pout->t = pv[4]; scale = xscale * pout->zi; pout->u = (xcenter + scale * transformed[0]); scale = yscale * pout->zi; pout->v = (ycenter - scale * transformed[1]); pv += sizeof (vec5_t) / sizeof (*pv); } // draw it r_spritedesc.nump = nump; r_spritedesc.pverts = outverts; D_DrawSprite (); }
void R_RenderFace (msurface_t *fa, int clipflags) { int i, lindex; unsigned mask; mplane_t *pplane; float distinv; vec3_t p_normal; medge_t *pedges, tedge; clipplane_t *pclip; // skip out if no more surfs if (surface_p >= surf_max) { r_outofsurfaces++; return; } // ditto if not enough edges left, or switch to auxedges if possible if ((edge_p + fa->numedges + 4) >= edge_max) { r_outofedges += fa->numedges; return; } c_faceclip++; // set up clip planes pclip = NULL; for (i = 3, mask = 0x08; i >= 0; i--, mask >>= 1) { if (clipflags & mask) { view_clipplanes[i].next = pclip; pclip = &view_clipplanes[i]; } } // push the edges through r_emitted = 0; r_nearzi = 0; r_nearzionly = false; makeleftedge = makerightedge = false; pedges = currententity->model->edges; r_lastvertvalid = false; for (i = 0; i < fa->numedges; i++) { lindex = currententity->model->surfedges[fa->firstedge + i]; if (lindex > 0) { r_pedge = &pedges[lindex]; // if the edge is cached, we can just reuse the edge if (!insubmodel) { if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED) { if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) == r_framecount) { r_lastvertvalid = false; continue; } } else { if ((((unsigned long)edge_p - (unsigned long)r_edges) > r_pedge->cachededgeoffset) && (((edge_t *)((unsigned long) r_edges + r_pedge->cachededgeoffset))->owner == r_pedge)) { R_EmitCachedEdge (); r_lastvertvalid = false; continue; } } } // assume it's cacheable cacheoffset = (byte *)edge_p - (byte *)r_edges; r_leftclipped = r_rightclipped = false; R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[0]], &r_pcurrentvertbase[r_pedge->v[1]], pclip); r_pedge->cachededgeoffset = cacheoffset; if (r_leftclipped) makeleftedge = true; if (r_rightclipped) makerightedge = true; r_lastvertvalid = true; } else { lindex = -lindex; r_pedge = &pedges[lindex]; // if the edge is cached, we can just reuse the edge if (!insubmodel) { if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED) { if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) == r_framecount) { r_lastvertvalid = false; continue; } } else { // it's cached if the cached edge is valid and is owned by this medge_t if ((((unsigned long)edge_p - (unsigned long)r_edges) > r_pedge->cachededgeoffset) && (((edge_t *)((unsigned long)r_edges + r_pedge->cachededgeoffset))->owner == r_pedge)) { R_EmitCachedEdge (); r_lastvertvalid = false; continue; } } } // assume it's cacheable cacheoffset = (byte *)edge_p - (byte *)r_edges; r_leftclipped = r_rightclipped = false; R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[1]], &r_pcurrentvertbase[r_pedge->v[0]], pclip); r_pedge->cachededgeoffset = cacheoffset; if (r_leftclipped) makeleftedge = true; if (r_rightclipped) makerightedge = true; r_lastvertvalid = true; } } // if there was a clip off the left edge, add that edge too // FIXME: faster to do in screen space? // FIXME: share clipped edges? if (makeleftedge) { r_pedge = &tedge; r_lastvertvalid = false; R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next); } // if there was a clip off the right edge, get the right r_nearzi if (makerightedge) { r_pedge = &tedge; r_lastvertvalid = false; r_nearzionly = true; R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next); } // if no edges made it out, return without posting the surface if (!r_emitted) return; r_polycount++; surface_p->data = (void *)fa; surface_p->nearzi = r_nearzi; surface_p->flags = fa->flags; surface_p->insubmodel = insubmodel; surface_p->spanstate = 0; surface_p->entity = currententity; surface_p->key = r_currentkey++; surface_p->spans = NULL; pplane = fa->plane; // FIXME: cache this? TransformVector (pplane->normal, p_normal); // FIXME: cache this? distinv = 1.0 / (-PlaneDiff(modelorg, pplane)); surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv; surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv; surface_p->d_ziorigin = p_normal[2] * distinv - xcenter * surface_p->d_zistepu - ycenter * surface_p->d_zistepv; surface_p++; }
void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf) { int i; unsigned mask; mplane_t *pplane; float distinv; vec3_t p_normal; medge_t tedge; clipplane_t *pclip; // skip out if no more surfs if (surface_p >= surf_max) { r_outofsurfaces++; return; } // ditto if not enough edges left, or switch to auxedges if possible if ((edge_p + psurf->numedges + 4) >= edge_max) { r_outofedges += psurf->numedges; return; } c_faceclip++; // this is a dummy to give the caching mechanism someplace to write to r_pedge = &tedge; // set up clip planes pclip = NULL; for (i = 3, mask = 0x08 ; i >= 0 ; i--, mask >>= 1) { if (r_clipflags & mask) { view_clipplanes[i].next = pclip; pclip = &view_clipplanes[i]; } } // push the edges through r_emitted = 0; r_nearzi = 0; r_nearzionly = false; makeleftedge = makerightedge = false; // FIXME: keep clipped bmodel edges in clockwise order so last vertex caching can be used? r_lastvertvalid = false; for ( ; pedges ; pedges = pedges->pnext) { r_leftclipped = r_rightclipped = false; R_ClipEdge (pedges->v[0], pedges->v[1], pclip); if (r_leftclipped) makeleftedge = true; if (r_rightclipped) makerightedge = true; } // if there was a clip off the left edge, add that edge too // FIXME: faster to do in screen space? // FIXME: share clipped edges? if (makeleftedge) { r_pedge = &tedge; R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next); } // if there was a clip off the right edge, get the right r_nearzi if (makerightedge) { r_pedge = &tedge; r_nearzionly = true; R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next); } // if no edges made it out, return without posting the surface if (!r_emitted) return; r_polycount++; surface_p->data = (void *)psurf; surface_p->nearzi = r_nearzi; surface_p->flags = psurf->flags; surface_p->insubmodel = true; surface_p->spanstate = 0; surface_p->entity = currententity; surface_p->key = r_currentbkey; surface_p->spans = NULL; pplane = psurf->plane; // FIXME: cache this? TransformVector (pplane->normal, p_normal); // FIXME: cache this? distinv = 1.0 / (-PlaneDiff(modelorg, pplane)); surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv; surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv; surface_p->d_ziorigin = p_normal[2] * distinv - xcenter * surface_p->d_zistepu - ycenter * surface_p->d_zistepv; surface_p++; }
int32 FSlateTextLayout::OnPaint( const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled ) const { const FSlateRect ClippingRect = AllottedGeometry.GetClippingRect().IntersectionWith(MyClippingRect); const ESlateDrawEffect::Type DrawEffects = bParentEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect; static bool ShowDebug = false; FLinearColor BlockHue( 0, 1.0f, 1.0f, 0.5 ); int32 HighestLayerId = LayerId; for (const FTextLayout::FLineView& LineView : LineViews) { // Is this line visible? const FSlateRect LineViewRect(AllottedGeometry.AbsolutePosition + LineView.Offset, AllottedGeometry.AbsolutePosition + LineView.Offset + LineView.Size); const FSlateRect VisibleLineView = ClippingRect.IntersectionWith(LineViewRect); if (VisibleLineView.IsEmpty()) { continue; } // Render any underlays for this line const int32 HighestUnderlayLayerId = OnPaintHighlights( Args, LineView, LineView.UnderlayHighlights, DefaultTextStyle, AllottedGeometry, ClippingRect, OutDrawElements, LayerId, InWidgetStyle, bParentEnabled ); const int32 BlockDebugLayer = HighestUnderlayLayerId; const int32 TextLayer = BlockDebugLayer + 1; int32 HighestBlockLayerId = TextLayer; // Render every block for this line for (const TSharedRef< ILayoutBlock >& Block : LineView.Blocks) { if ( ShowDebug ) { BlockHue.R += 50.0f; // The block size and offset values are pre-scaled, so we need to account for that when converting the block offsets into paint geometry const float InverseScale = Inverse(AllottedGeometry.Scale); FSlateDrawElement::MakeBox( OutDrawElements, BlockDebugLayer, AllottedGeometry.ToPaintGeometry(TransformVector(InverseScale, Block->GetSize()), FSlateLayoutTransform(TransformPoint(InverseScale, Block->GetLocationOffset()))), &DefaultTextStyle.HighlightShape, ClippingRect, DrawEffects, InWidgetStyle.GetColorAndOpacityTint() * BlockHue.HSVToLinearRGB() ); } const TSharedRef< ISlateRun > Run = StaticCastSharedRef< ISlateRun >( Block->GetRun() ); int32 HighestRunLayerId = TextLayer; const TSharedPtr< ISlateRunRenderer > RunRenderer = StaticCastSharedPtr< ISlateRunRenderer >( Block->GetRenderer() ); if ( RunRenderer.IsValid() ) { HighestRunLayerId = RunRenderer->OnPaint( Args, LineView, Run, Block, DefaultTextStyle, AllottedGeometry, ClippingRect, OutDrawElements, TextLayer, InWidgetStyle, bParentEnabled ); } else { HighestRunLayerId = Run->OnPaint( Args, LineView, Block, DefaultTextStyle, AllottedGeometry, ClippingRect, OutDrawElements, TextLayer, InWidgetStyle, bParentEnabled ); } HighestBlockLayerId = FMath::Max( HighestBlockLayerId, HighestRunLayerId ); } // Render any overlays for this line const int32 HighestOverlayLayerId = OnPaintHighlights( Args, LineView, LineView.OverlayHighlights, DefaultTextStyle, AllottedGeometry, ClippingRect, OutDrawElements, HighestBlockLayerId, InWidgetStyle, bParentEnabled ); HighestLayerId = FMath::Max( HighestLayerId, HighestOverlayLayerId ); } return HighestLayerId; }
/*********************************************************************** ComputeInitLink() - this function computes the initial end points, u,v,n vectors, and rotation matrix for the specified link. for the given link set visible end to origin + vislen set actual end to origin + totlen rotate both points by theta about z axis translate both points to actual end of previous link compute u,v,n vectors map end points to screen coordinates ***********************************************************************/ int ComputeInitLink(int link, MyProgram *data) { vectorType o2, o2prime, o3, o3prime; vectorType p1, p2, p3; vectorType u, v, vprime, n; double world[4]; double screen[4]; matrixType translation; matrixType rotation; matrixType screen_map; pointType MapWPointToScreen(wpointType *p, matrixType *map); /* set actual end to origin + totlen */ o3.x = data->links[link].total_length; o3.y = 0.0; o3.z = 0.0; /* set visible end to origin + vislen */ o2.x = data->links[link].visible_length; o2.y = 0.0; o2.z = 0.0; /* make rotation matrix */ rotation = MakeRotationMatrix('z', data->links[link].zrot_deg); MatrixCopy(&rotation, &data->links[link].rot_mat); /* rotate actual and visible end points around z axis */ o3prime = TransformVector(&o3, &rotation); /* o3prime = o3 * Rz(theta) */ o2prime = TransformVector(&o2, &rotation); /* o2prime = o2 * Rz(theta) */ /* set start of link to actual end of previous link if not root link */ if (data->links[link].type == LINK_ROOT) { /* root link */ p1.x = data->links[link].w_start.x; p1.y = data->links[link].w_start.y; p1.z = data->links[link].w_start.z; } else { /* normal link */ p1.x = data->links[link - 1].w_end.x; p1.y = data->links[link - 1].w_end.y; p1.z = data->links[link - 1].w_end.z; } /* make translation matrix */ translation = MakeTranslationMatrix(p1.x, p1.y, p1.z); /* translate actual end and visible end to final locations */ p3 = TransformVector(&o3prime, &translation); /* p3 = o3prime * T(ox,oy,oz) */ p2 = TransformVector(&o2prime, &translation); /* p2 = o2prime * T(ox,oy,oz) */ /* copy final end locations to link data */ data->links[link].w_end.x = p3.x; /* actual end */ data->links[link].w_end.y = p3.y; data->links[link].w_end.z = p3.z; data->links[link].w_visend.x = p2.x; /* visible end */ data->links[link].w_visend.y = p2.y; data->links[link].w_visend.z = p2.z; data->links[link].w_start.x = p1.x; /* start point */ data->links[link].w_start.y = p1.y; data->links[link].w_start.z = p1.z; /* compute u vector */ u = VecSub(&p1, &p3); /* u = p3 - p1 */ VecNormalize(&u); /* u = u / mag(u) */ /* compute n vector */ vprime.x = 0.0; vprime.y = 1.0; vprime.z = 0.0; n = VecCrossproduct(&u, &vprime); /* n = u X vprime */ /* compute v vector */ v = VecCrossproduct(&n, &u); /* v = n X u */ /* copy u,v,n vectors to link data */ data->links[link].u_vec.x = u.x; data->links[link].u_vec.y = u.y; data->links[link].u_vec.z = u.z; data->links[link].v_vec.x = v.x; data->links[link].v_vec.y = v.y; data->links[link].v_vec.z = v.z; data->links[link].n_vec.x = n.x; data->links[link].n_vec.y = n.y; data->links[link].n_vec.z = n.z; /* map start and end points to screen coordinates */ world[0] = WB_MINX; world[1] = WB_MINY; world[2] = WB_MAXX; world[3] = WB_MAXY; screen[0] = 0.0; screen[1] = 0.0; screen[2] = SCREEN_X_SIZE; screen[3] = SCREEN_Y_SIZE; screen_map = MakeMappingMatrix(world, screen); data->links[link].start = MapWPointToScreen( &data->links[link].w_start, &screen_map); data->links[link].end = MapWPointToScreen( &data->links[link].w_end, &screen_map); data->links[link].visend = MapWPointToScreen( &data->links[link].w_visend, &screen_map); #ifdef INVKINE_DEBUG OutputLink(stdout, data, link); #endif return(0); } /* end of ComputeInitLink() */
/* ================ R_RenderPoly ================ */ void R_RenderPoly(msurface_t *fa, int clipflags) { int i, lindex, lnumverts, s_axis, t_axis; float dist, lastdist, lzi, scale, u, v, frac; unsigned mask; vec3_t local, transformed; clipplane_t *pclip; medge_t *pedges; mplane_t *pplane; mvertex_t verts[2][100]; //FIXME: do real number polyvert_t pverts[100]; //FIXME: do real number, safely int vertpage, newverts, newpage, lastvert; qboolean visible; // FIXME: clean this up and make it faster // FIXME: guard against running out of vertices s_axis = t_axis = 0; // keep compiler happy // set up clip planes pclip = NULL; for (i = 3, mask = 0x08; i >= 0; i--, mask >>= 1) { if (clipflags & mask) { view_clipplanes[i].next = pclip; pclip = &view_clipplanes[i]; } } // reconstruct the polygon // FIXME: these should be precalculated and loaded off disk pedges = currententity->model->edges; lnumverts = fa->numedges; vertpage = 0; for (i = 0; i < lnumverts; i++) { lindex = currententity->model->surfedges[fa->firstedge + i]; if (lindex > 0) { r_pedge = &pedges[lindex]; verts[0][i] = r_pcurrentvertbase[r_pedge->v[0]]; } else { r_pedge = &pedges[-lindex]; verts[0][i] = r_pcurrentvertbase[r_pedge->v[1]]; } } // clip the polygon, done if not visible while (pclip) { lastvert = lnumverts - 1; lastdist = DotProduct(verts[vertpage][lastvert].position, pclip->normal) - pclip->dist; visible = false; newverts = 0; newpage = vertpage ^ 1; for (i = 0; i < lnumverts; i++) { dist = DotProduct(verts[vertpage][i].position, pclip->normal) - pclip->dist; if ((lastdist > 0) != (dist > 0)) { frac = dist / (dist - lastdist); verts[newpage][newverts].position[0] = verts[vertpage][i].position[0] + ((verts[vertpage][lastvert].position[0] - verts[vertpage][i].position[0]) * frac); verts[newpage][newverts].position[1] = verts[vertpage][i].position[1] + ((verts[vertpage][lastvert].position[1] - verts[vertpage][i].position[1]) * frac); verts[newpage][newverts].position[2] = verts[vertpage][i].position[2] + ((verts[vertpage][lastvert].position[2] - verts[vertpage][i].position[2]) * frac); newverts++; } if (dist >= 0) { verts[newpage][newverts] = verts[vertpage][i]; newverts++; visible = true; } lastvert = i; lastdist = dist; } if (!visible || (newverts < 3)) return; lnumverts = newverts; vertpage ^= 1; pclip = pclip->next; } // transform and project, remembering the z values at the vertices and // r_nearzi, and extract the s and t coordinates at the vertices pplane = fa->plane; switch (pplane->type) { case PLANE_X: case PLANE_ANYX: s_axis = 1; t_axis = 2; break; case PLANE_Y: case PLANE_ANYY: s_axis = 0; t_axis = 2; break; case PLANE_Z: case PLANE_ANYZ: s_axis = 0; t_axis = 1; break; } r_nearzi = 0; for (i = 0; i < lnumverts; i++) { // transform and project VectorSubtract(verts[vertpage][i].position, modelorg, local); TransformVector(local, transformed); if (transformed[2] < NEAR_CLIP) transformed[2] = NEAR_CLIP; lzi = 1.0 / transformed[2]; if (lzi > r_nearzi) // for mipmap finding r_nearzi = lzi; // FIXME: build x/yscale into transform? scale = xscale * lzi; u = (xcenter + scale * transformed[0]); if (u < r_refdef.fvrectx_adj) u = r_refdef.fvrectx_adj; if (u > r_refdef.fvrectright_adj) u = r_refdef.fvrectright_adj; scale = yscale * lzi; v = (ycenter - scale * transformed[1]); if (v < r_refdef.fvrecty_adj) v = r_refdef.fvrecty_adj; if (v > r_refdef.fvrectbottom_adj) v = r_refdef.fvrectbottom_adj; pverts[i].u = u; pverts[i].v = v; pverts[i].zi = lzi; pverts[i].s = verts[vertpage][i].position[s_axis]; pverts[i].t = verts[vertpage][i].position[t_axis]; } // build the polygon descriptor, including fa, r_nearzi, and u, v, s, t, and z // for each vertex r_polydesc.numverts = lnumverts; r_polydesc.nearzi = r_nearzi; r_polydesc.pcurrentface = fa; r_polydesc.pverts = pverts; // draw the polygon D_DrawPoly(); }
Vector3 Frame::AxisY(const Date& t, const Frame& ref) const { return TransformVector(Vector3::j, t, ref); }
FVector2D SFxWidget::ComputeDesiredSize() const { // Layout scale affects out desired size. return TransformVector(LayoutScale.Get(), ChildSlot.GetWidget()->GetDesiredSize()); }
//================================================================================================================================= /// Measure overdraw from a particular viewpoint. /// /// \param pCameraPosition Camera position to use for this viewpoint. The camera will be looking at the origin /// \param nImageSize Size of the pixel grid on each axis /// \param bCullCCW Set to true to cull CCW faces, otherwise cull CW faces. /// \param fAvgODOut A variable to receive the average overdraw per pixel. /// /// \return False if out of memory. True otherwise //================================================================================================================================= bool TootleRaytracer::ProcessViewpoint(const float* pCameraPosition, UINT nImageSize, bool bCullCCW, UINT& nPixelHit, UINT& nPixelDrawn) { assert(pCameraPosition); if (nImageSize < 1) { nImageSize = 1; // a strange 1x1 image } // build camera basis vectors Vec3f position(pCameraPosition); Vec3f viewDir = Normalize(position) * -1.0; Vec3f up; // Compute the up vector by performing 90 degree 2D rotation on the position vector // (choose two good component vectors). if ((position[ 1 ] * position[ 1 ]) < (position[ 0 ] * position[ 0 ])) { up[ 0 ] = -position[ 2 ]; up[ 1 ] = 0; up[ 2 ] = position[ 0 ]; } else { up[ 0 ] = 0; up[ 1 ] = position[ 2 ]; up[ 2 ] = -position[ 1 ]; } up = Normalize(up); Matrix4f mLookAt = MatrixLookAt(position, Vec3f(0, 0, 0), up); // choose viewport size: // transform bounding box corners into viewing space // as we do this, track the bounding square of the x and y coordinates // we will take the size of the larger dimension to be the viewport size Vec3f corners[8]; m_pCore->GetSceneBB().GetCorners(corners); float xmin = FLT_MAX; float xmax = -FLT_MAX; float ymin = FLT_MAX; float ymax = -FLT_MAX; for (int i = 0; i < 8; i++) { TransformVector(&corners[i], &mLookAt, &corners[i]); xmin = Min(xmin, corners[i].x); xmax = Max(xmax, corners[i].x); ymin = Min(ymin, corners[i].y); ymax = Max(ymax, corners[i].y); } float fViewSize = Max(xmax - xmin, ymax - ymin) * 2; //float fViewSize = sqrt(pow(xmax-xmin,2) + pow(ymax-ymin,2)); //Max( xmax - xmin, ymax - ymin ); // build the camera JRTOrthoCamera camera(position, viewDir, up, fViewSize); // cull backfaces m_pCore->CullBackfaces(viewDir, bCullCCW); // iterate over the pixels that we're interested in float delta = 1.0f / nImageSize; float s = 0; float t = 0; #ifdef DEBUG_IMAGES JRTPPMImage img(nImageSize, nImageSize); #endif UINT nPixelDrawnTmp; nPixelHit = 0; nPixelDrawn = 0; for (int i = 0; i < (int) nImageSize; i++) { for (int j = 0; j < (int) nImageSize; j++) { // compute the camera ray for this pixel Vec3f rayOrigin, rayDirection; camera.GetRay(s, t, &rayOrigin, &rayDirection); // trace through the scene data structures to find all hits TootleRayHit* pHitArray = 0; UINT nHits = 0; if (!m_pCore->FindAllHits(rayOrigin, rayDirection, &pHitArray, &nHits)) { // ran out of memory return false; } if (nHits > 0) { nPixelHit++; // compute the number of triangles overdrawn for the pixel GetPixelDrawn(pHitArray, nHits, nPixelDrawnTmp); nPixelDrawn += nPixelDrawnTmp; } #ifdef DEBUG_IMAGES float clr = nHits / 8.f; img.SetPixel(j, i, clr, clr, clr); /*if( nHits > 0 ) { UINT nTriIndex = pHitArray[0].nFaceID; Vec3f normal = m_pMesh->GetFaceNormal( nTriIndex ); normal /= 2; normal += Vec3f(0.5,0.5,0.5); img.SetPixel( j, i, normal.x, normal.y, normal.z ); }*/ #endif s += delta; } t += delta; s = 0; } #ifdef DEBUG_IMAGES static int nFrameNum = 0; char filename[100]; sprintf(filename, "C:/tmp/images/view_%d.ppm", nFrameNum); img.SaveFile(filename); nFrameNum++; #endif return true; }
// Draw the scene to the screen void draw() { // Update time time += 2.0f * timeStep; /////////////////////// PART 1: SIMULATION ///////////////////////////////// // Grab buffers for OpenCL acquireGLBuffer(particles.particleBuffer[particles.currentBuffer]); acquireGLBuffer(particles.particleBuffer[1 - particles.currentBuffer]); // Prepare to run some kernels cl_int numParticles = NUM_PARTICLES; cl_int gridElements = GRID_SIZE * GRID_SIZE * GRID_SIZE; cl_uint workSize[3] = {numParticles, 0, 0}; cl_uint gridWorkSize[3] = {gridElements, 0, 0}; cl_uint workgroupSize[3] = {256, 0, 0}; // Clear grid clSetKernelArg(openCLKernels.gridClearKernel, 0, sizeof(cl_mem), &particles.gridSizeBuffer); clSetKernelArg(openCLKernels.gridClearKernel, 1, sizeof(cl_int), &gridElements); clRunKernel(openCLKernels.gridClearKernel, gridWorkSize, workgroupSize); // Compute grid positions clSetKernelArg(openCLKernels.gridKernel, 0, sizeof(cl_mem), &particles.particleBuffer[particles.currentBuffer]); clSetKernelArg(openCLKernels.gridKernel, 1, sizeof(cl_mem), &particles.offsetBuffer); clSetKernelArg(openCLKernels.gridKernel, 2, sizeof(cl_mem), &particles.gridSizeBuffer); clSetKernelArg(openCLKernels.gridKernel, 3, sizeof(cl_int), &numParticles); clRunKernel(openCLKernels.gridKernel, workSize, workgroupSize); // Compute prefix sum for grid clSetKernelArg(openCLKernels.prefixSumKernel, 2, sizeof(cl_uint), (void*)&gridElements); int pingpong = 0; for(cl_int offset = 1; offset <= gridElements; offset *= 2) { if(offset == 1) { clSetKernelArg(openCLKernels.prefixSumKernel, 0, sizeof(cl_mem), (void*)&particles.gridSizeBuffer); } else { clSetKernelArg(openCLKernels.prefixSumKernel, 0, sizeof(cl_mem), (void*)&(pingpong == 0 ? particles.gridBuffer[0] : particles.gridBuffer[1])); } clSetKernelArg(openCLKernels.prefixSumKernel, 1, sizeof(cl_mem), (void*)&(pingpong == 0 ? particles.gridBuffer[1] : particles.gridBuffer[0])); clSetKernelArg(openCLKernels.prefixSumKernel, 3, sizeof(cl_int), (void*)&offset); clRunKernel(openCLKernels.prefixSumKernel, gridWorkSize, workgroupSize); pingpong = 1 - pingpong; } // Reorganize particles clSetKernelArg(openCLKernels.gridReorderKernel, 0, sizeof(cl_mem), &particles.particleBuffer[particles.currentBuffer]); clSetKernelArg(openCLKernels.gridReorderKernel, 1, sizeof(cl_mem), &particles.particleBuffer[1 - particles.currentBuffer]); clSetKernelArg(openCLKernels.gridReorderKernel, 2, sizeof(cl_mem), &particles.velocityBuffer[particles.currentBuffer]); clSetKernelArg(openCLKernels.gridReorderKernel, 3, sizeof(cl_mem), &particles.velocityBuffer[1 - particles.currentBuffer]); clSetKernelArg(openCLKernels.gridReorderKernel, 4, sizeof(cl_mem), &particles.offsetBuffer); clSetKernelArg(openCLKernels.gridReorderKernel, 5, sizeof(cl_mem), (void*)&particles.gridSizeBuffer); clSetKernelArg(openCLKernels.gridReorderKernel, 6, sizeof(cl_mem), (void*)&(pingpong == 0 ? particles.gridBuffer[0] : particles.gridBuffer[1])); clSetKernelArg(openCLKernels.gridReorderKernel, 7, sizeof(cl_int), &numParticles); clRunKernel(openCLKernels.gridReorderKernel, workSize, workgroupSize); particle* testData = (particle*)malloc(sizeof(cl_float) * numParticles * 4); // Swap particle buffers particles.currentBuffer = 1 - particles.currentBuffer; // Send new cell select buffer int cellSelect[27]; for(int i = 0; i < 27; i++) { cellSelect[i] = i; } shuffle(cellSelect, 27); clEnqueueWriteBuffer(clCommandQueue(), particles.cellSelectBuffer, true, 0, 27 * sizeof(cl_int), cellSelect, 0, 0, 0); clFinish(clCommandQueue()); // Recalculate densities and normalized pressure derivatives clSetKernelArg(openCLKernels.dataKernel, 0, sizeof(cl_mem), &particles.particleBuffer[particles.currentBuffer]); clSetKernelArg(openCLKernels.dataKernel, 1, sizeof(cl_mem), &particles.dataBuffer); clSetKernelArg(openCLKernels.dataKernel, 2, sizeof(cl_mem), (void*)&particles.gridSizeBuffer); clSetKernelArg(openCLKernels.dataKernel, 3, sizeof(cl_mem), (void*)&(pingpong == 0 ? particles.gridBuffer[1] : particles.gridBuffer[0])); clSetKernelArg(openCLKernels.dataKernel, 4, sizeof(cl_mem), (void*)&particles.cellSelectBuffer); clSetKernelArg(openCLKernels.dataKernel, 5, sizeof(cl_int), &numParticles); clRunKernel(openCLKernels.dataKernel, workSize, workgroupSize); // Send new cell select buffer cellSelect[27]; for(int i = 0; i < 27; i++) { cellSelect[i] = i; } shuffle(cellSelect, 27); clEnqueueWriteBuffer(clCommandQueue(), particles.cellSelectBuffer, true, 0, 27 * sizeof(cl_int), cellSelect, 0, 0, 0); clFinish(clCommandQueue()); // Integrate position float dT = timeStep; clSetKernelArg(openCLKernels.simulationKernel, 0, sizeof(cl_mem), &particles.particleBuffer[particles.currentBuffer]); clSetKernelArg(openCLKernels.simulationKernel, 1, sizeof(cl_mem), &particles.particleBuffer[1 - particles.currentBuffer]); clSetKernelArg(openCLKernels.simulationKernel, 2, sizeof(cl_mem), &particles.velocityBuffer[particles.currentBuffer]); clSetKernelArg(openCLKernels.simulationKernel, 3, sizeof(cl_mem), &particles.velocityBuffer[1 - particles.currentBuffer]); clSetKernelArg(openCLKernels.simulationKernel, 4, sizeof(cl_mem), &particles.dataBuffer); clSetKernelArg(openCLKernels.simulationKernel, 5, sizeof(cl_mem), (void*)&particles.gridSizeBuffer); clSetKernelArg(openCLKernels.simulationKernel, 6, sizeof(cl_mem), (void*)&(pingpong == 0 ? particles.gridBuffer[1] : particles.gridBuffer[0])); clSetKernelArg(openCLKernels.simulationKernel, 7, sizeof(cl_mem), (void*)&particles.cellSelectBuffer); clSetKernelArg(openCLKernels.simulationKernel, 8, sizeof(cl_float), &dT); clSetKernelArg(openCLKernels.simulationKernel, 9, sizeof(cl_float), &time); clSetKernelArg(openCLKernels.simulationKernel, 10, sizeof(cl_int), &numParticles); clSetKernelArg(openCLKernels.simulationKernel, 11, sizeof(cl_mem), &particles.terrainBuffer); PaddedVector windDir = PadVector( TransformVector(YAxisRotationMatrix(particles.windAngle), MakeVector(1.0f, 0.0f, 0.0f)) ); clSetKernelArg(openCLKernels.simulationKernel, 12, sizeof(cl_float) * 4, &windDir); clSetKernelArg(openCLKernels.simulationKernel, 13, sizeof(cl_float), &particles.windPower); clRunKernel(openCLKernels.simulationKernel, workSize, workgroupSize); // Release buffers back to OpenGL releaseGLBuffer(particles.particleBuffer[particles.currentBuffer]); releaseGLBuffer(particles.particleBuffer[1 - particles.currentBuffer]); // Swap particle buffers particles.currentBuffer = 1 - particles.currentBuffer; //////////////////////// PART 2: RENDERIING //////////////////////////////// // Clear everything first thing. glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glBindFramebuffer(GL_FRAMEBUFFER, framebuffers.backgroundFBO); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Activate shader. glUseProgram(objectShader.shaderProgram); // Set projection Matrix projection = PerspectiveMatrix( 45.0f, (float)WINDOW_WIDTH/(float)WINDOW_HEIGHT, 0.01f, 100.0f ); MatrixAsUniform(objectShader.projectionMatrix, projection); // Vertices glBindBuffer(GL_ARRAY_BUFFER, terrain.vertexBuffer); glVertexAttribPointer( objectShader.vertexPosition, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, (void*)0 ); glEnableVertexAttribArray(objectShader.vertexPosition); // Set modelview according to camera Matrix rot = lookatMatrix(camera.pos, VectorAdd(camera.pos, camera.front), camera.up); rot = MatrixMul(RotationMatrix(camera.elevation, MakeVector(1, 0, 0)), rot); Matrix trans = TranslationMatrix(-camera.pos.x, -camera.pos.y, -camera.pos.z); Matrix modelview = MatrixMul(rot, trans); MatrixAsUniform(objectShader.modelviewMatrix, modelview); // Normal view matrix - inverse transpose of modelview. Matrix normalview = MatrixTranspose(FastMatrixInverse(modelview)); MatrixAsUniform(objectShader.normalviewMatrix, normalview); // Set heightmap texture glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, terrain.heightTexture ); glUniform1i(objectShader.terrainTexture, 0); // Set color textures glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, terrain.lowTexture); glUniform1i(objectShader.lowTexture, 1); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, terrain.highTexture); glUniform1i(objectShader.highTexture, 2); // Turn off culling glDisable(GL_CULL_FACE); // Send element buffer to GPU and draw. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, terrain.elementBuffer); glDrawElements( GL_TRIANGLES, 512 * 512 * 6, GL_UNSIGNED_INT, (void*)0 ); // Turn culling back on glEnable(GL_CULL_FACE); // Switch to low-res viewport glViewport(0, 0, WINDOW_WIDTH / RESOLUTION_DIVIDER, WINDOW_HEIGHT / RESOLUTION_DIVIDER); // Low-res projection matrix Matrix projectionLowres = PerspectiveMatrix( 45.0f, (float)(WINDOW_WIDTH / RESOLUTION_DIVIDER) / (float)(WINDOW_HEIGHT / RESOLUTION_DIVIDER), 0.01f, 100.0f ); // Activate particle depth FBO glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glBindFramebuffer(GL_FRAMEBUFFER, framebuffers.particleFBO[0]); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Activate shader glUseProgram(particleShader.shaderProgram); // Set textures glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, framebuffers.backgroundTexture); glUniform1i(particleShader.terrainTexture, 0); // Send uniforms MatrixAsUniform(particleShader.modelviewMatrix, modelview); MatrixAsUniform(particleShader.projectionMatrix, projectionLowres); glUniform2f(particleShader.screenSize, WINDOW_WIDTH / RESOLUTION_DIVIDER, WINDOW_HEIGHT / RESOLUTION_DIVIDER); // Bind new buffer and set up arrtibutes glBindBuffer(GL_ARRAY_BUFFER, particles.vertexBuffer[particles.currentBuffer]); glVertexAttribPointer( particleShader.vertexPosition, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, (void*)0 ); glEnableVertexAttribArray(particleShader.vertexPosition); // Bind element buffer and draw particles glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, particles.elementBuffer); glDrawElements( GL_POINTS, NUM_PARTICLES, GL_UNSIGNED_INT, (void*)0 ); // Activate particle thickness FBO glBindFramebuffer(GL_FRAMEBUFFER, framebuffers.particleThicknessFBO[0]); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Activate shader glUseProgram(particleThicknessShader.shaderProgram); // Send uniforms MatrixAsUniform(particleThicknessShader.modelviewMatrix, modelview); MatrixAsUniform(particleThicknessShader.projectionMatrix, projectionLowres); glUniform2f(particleThicknessShader.screenSize, WINDOW_WIDTH / RESOLUTION_DIVIDER, WINDOW_HEIGHT / RESOLUTION_DIVIDER); // Set textures glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, framebuffers.backgroundTexture); glUniform1i(particleThicknessShader.terrainTexture, 0); // Bind new buffer and set up arrtibutes glBindBuffer(GL_ARRAY_BUFFER, particles.vertexBuffer[particles.currentBuffer]); glVertexAttribPointer( particleThicknessShader.vertexPosition, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, (void*)0 ); glEnableVertexAttribArray(particleThicknessShader.vertexPosition); // Enable additive blending and disable depth test glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); glDisable(GL_DEPTH_TEST); // Bind element buffer and draw particles, this time rendering thickness map glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, particles.elementBuffer); glDrawElements( GL_POINTS, NUM_PARTICLES, GL_UNSIGNED_INT, (void*)0 ); // Turn blending back off and depth test back on glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); // Activate particle velocity FBO glBindFramebuffer(GL_FRAMEBUFFER, framebuffers.velocityFBO); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Activate shader glUseProgram(particleVelocityShader.shaderProgram); // Send uniforms MatrixAsUniform(particleVelocityShader.modelviewMatrix, modelview); MatrixAsUniform(particleVelocityShader.projectionMatrix, projectionLowres); glUniform2f(particleVelocityShader.screenSize, WINDOW_WIDTH / RESOLUTION_DIVIDER, WINDOW_HEIGHT / RESOLUTION_DIVIDER); // Bind new buffer and set up arrtibutes glBindBuffer(GL_ARRAY_BUFFER, particles.vertexBuffer[particles.currentBuffer]); glVertexAttribPointer( particleVelocityShader.vertexPosition, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, (void*)0 ); glEnableVertexAttribArray(particleVelocityShader.vertexPosition); // Bind element buffer and draw particles, this time rendering velocity map glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, particles.elementBuffer); glDrawElements( GL_POINTS, NUM_PARTICLES, GL_UNSIGNED_INT, (void*)0 ); // Curvature flow smoothing begins glUseProgram(curvatureFlowShader.shaderProgram); // Send uniforms glUniform1i(curvatureFlowShader.particleTexture, 0); glUniform2f(curvatureFlowShader.screenSize, WINDOW_WIDTH / RESOLUTION_DIVIDER, WINDOW_HEIGHT / RESOLUTION_DIVIDER); MatrixAsUniform(curvatureFlowShader.projectionMatrix, projectionLowres); // Prepare state glActiveTexture(GL_TEXTURE0); glBindBuffer(GL_ARRAY_BUFFER, screenQuad.vertexBuffer); glVertexAttribPointer( curvatureFlowShader.vertexPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, (void*)0 ); glEnableVertexAttribArray(curvatureFlowShader.vertexPosition); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, screenQuad.elementBuffer); // Smoothing loop glDisable(GL_DEPTH_TEST); pingpong = 0; for(int i = 0; i < smoothingIterations; i++) { // Bind no FBO glBindFramebuffer(GL_FRAMEBUFFER, 0); // Bind texture glBindTexture(GL_TEXTURE_2D, framebuffers.particleTexture[pingpong]); // Activate proper FBO and clear glBindFramebuffer(GL_FRAMEBUFFER, framebuffers.particleFBO[1 - pingpong]); // Draw a quad glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)0 ); // Switch buffers pingpong = 1 - pingpong; } glEnable(GL_DEPTH_TEST); // Activate particle color FBO glBindFramebuffer(GL_FRAMEBUFFER, framebuffers.particleColorFBO); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Liquid shading shader glUseProgram(liquidShadeShader.shaderProgram); // Bind and set textures glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, framebuffers.particleTexture[0]); glUniform1i(liquidShadeShader.particleTexture, 0); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, framebuffers.particleThicknessTexture[0]); glUniform1i(liquidShadeShader.particleThicknessTexture, 1); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, terrain.envTexture); glUniform1i(liquidShadeShader.environmentTexture, 2); glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_2D, framebuffers.particleVelocityTexture); glUniform1i(liquidShadeShader.velocityTexture, 3); // Send uniforms glUniform2f(liquidShadeShader.screenSize, WINDOW_WIDTH, WINDOW_HEIGHT); MatrixAsUniform(liquidShadeShader.modelviewMatrix, modelview); MatrixAsUniform(liquidShadeShader.projectionMatrix, projection); glUniform1i(liquidShadeShader.useThickness, useThickness); // Draw a quad glDisable(GL_DEPTH_TEST); glBindBuffer(GL_ARRAY_BUFFER, screenQuad.vertexBuffer); glVertexAttribPointer( liquidShadeShader.vertexPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, (void*)0 ); glEnableVertexAttribArray(liquidShadeShader.vertexPosition); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, screenQuad.elementBuffer); glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)0 ); glEnable(GL_DEPTH_TEST); // Switch back to full-res viewport glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); // Deactivate FBOs glBindFramebuffer(GL_FRAMEBUFFER, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Compose shader glUseProgram(compositionShader.shaderProgram); // Bind and set textures glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, terrain.envTexture); glUniform1i(compositionShader.backgroundTexture, 0); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, framebuffers.particleColorTexture); glUniform1i(compositionShader.particleTexture, 1); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, framebuffers.backgroundTexture); glUniform1i(compositionShader.terrainTexture, 2); // Send uniforms MatrixAsUniform(compositionShader.modelviewMatrix, modelview); // Draw a quad glDisable(GL_DEPTH_TEST); glBindBuffer(GL_ARRAY_BUFFER, screenQuad.vertexBuffer); glVertexAttribPointer( compositionShader.vertexPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, (void*)0 ); glEnableVertexAttribArray(compositionShader.vertexPosition); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, screenQuad.elementBuffer); glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)0 ); glEnable(GL_DEPTH_TEST); // Switch drawing area and displayed area. glutSwapBuffers(); }
/******************************************************** * * * Draw Robot * * ********************************************************/ void Virtual3dCharacterViewer::glDrawBody(Character3DBody& body) { glPushMatrix(); // getHipPos() ; // get Hip's Position from the IK calculator . LocateHip (body); body.HipPosInCamera = getCurTranslation () ; body.HipPosInScreen = getScreenPos(body.HipPosInCamera) ; RotateHip(body) ; glPushMatrix(); // save the Hip Matrix drawHip (body) ; glTranslatef( 0.0, body.Model.LenHipToChest, 0.0 ) ; RotateChest (body); drawChest (body) ; glTranslatef(0.0, body.Model.LenChestToNeck, 0.0); body.NeckPosInCamera = getCurTranslation () ; body.NeckPos = TransformVector( WorldMatInv, body.NeckPosInCamera ) ; body.NeckPosInScreen = getScreenPos(body.NeckPosInCamera) ; glPushMatrix(); // save the Neck Matrix RotateLeftShoulder(body); drawLeftShoulder(body); glTranslatef(body.Model.LenNeckToShoulder, 0.0, 0.0); RotateLeftUpperArm(body); drawLeftUpperArm(body); glTranslatef(body.Model.LenShoulderToElbow, 0.0, 0.0); RotateLeftLowerArm(body); drawLeftLowerArm(body); glTranslatef(body.Model.LenElbowToWrist, 0.0, 0.0); body.LeftWristPosInCamera = getCurTranslation () ; Vector3D bias(-1,0,0) ; body.LeftWristPos = TransformVector( WorldMatInv, body.LeftWristPosInCamera ); body.LeftWristPosInScreen = getScreenPos(body.LeftWristPosInCamera) ; RotateLeftHand(body); drawLeftHand(body); glPopMatrix(); // reload the Neck Matrix glPushMatrix(); // restore the Neck Matrix again . RotateRightShoulder(body); drawRightShoulder(body); glTranslatef(-body.Model.LenNeckToShoulder, 0.0, 0.0); RotateRightUpperArm(body); drawRightUpperArm(body); glTranslatef(-body.Model.LenShoulderToElbow, 0.0, 0.0); RotateRightLowerArm(body); drawRightLowerArm(body); glTranslatef(-body.Model.LenElbowToWrist, 0.0, 0.0); body.RightWristPosInCamera = getCurTranslation () ; body.RightWristPos = TransformVector( WorldMatInv, body.RightWristPosInCamera ) ; body.RightWristPosInScreen = getScreenPos(body.RightWristPosInCamera) ; RotateRightHand(body); drawRightHand(body); glPopMatrix(); // reload the Neck Matrix again . RotateHead(body); drawHead (body); glTranslatef(0.0, body.Model.LenNeckToHead, 0.0); body.HeadPosInCamera = getCurTranslation () ; body.HeadPos = TransformVector( WorldMatInv, body.HeadPosInCamera ) ; body.HeadPosInScreen = getScreenPos(body.HeadPosInCamera) ; glPopMatrix(); // reload the Hip Matrix . glPushMatrix(); // restore the Hip Matrix again. RotateLeftThighRoot (body); drawLeftThighRoot(body); glTranslatef(body.Model.LenHipToThigh, 0.0, 0.0); RotateLeftThigh (body) ; drawLeftThigh(body); glTranslatef(0.0, -body.Model.LenThighToKnee, 0.0); RotateLeftShank(body); drawLeftShank(body); glTranslatef(0.0, -body.Model.LenKneeToAnkle, 0.0); body.LeftAnklePosInCamera = getCurTranslation(); body.LeftAnklePos = TransformVector( WorldMatInv, body.LeftAnklePosInCamera ) ; body.LeftAnklePosInScreen = getScreenPos(body.LeftAnklePosInCamera) ; RotateLeftFoot (body); drawLeftFoot(body); glPopMatrix(); // reload the Hip Matrix again. RotateRightThighRoot (body); drawRightThighRoot(body); glTranslatef(-body.Model.LenHipToThigh, 0.0, 0.0); RotateRightThigh (body) ; drawRightThigh(body); glTranslatef(0.0, -body.Model.LenThighToKnee, 0.0); RotateRightShank(body); drawRightShank(body); glTranslatef(0.0, -body.Model.LenKneeToAnkle, 0.0); body.RightAnklePosInCamera = getCurTranslation(); body.RightAnklePos = TransformVector( WorldMatInv, body.RightAnklePosInCamera ) ; body.RightAnklePosInScreen = getScreenPos(body.RightAnklePosInCamera) ; RotateRightFoot (body); drawRightFoot(body); glPopMatrix(); }
void TransformPlane(Plane& out, const Plane& in, const Float4x4& transform) { TransformVector( out.normal, in.normal, transform ); out.distance = in.distance + DotProduct( out.normal, transform.WAxis ); }
// Frame case bool Model3D::FindPositions_Frame(bool UseModelTransform, GLshort FrameIndex, GLfloat MixFrac, GLshort AddlFrameIndex) { // Bad inputs: do nothing and return false if (Frames.empty()) { return false; } size_t NumBones = Bones.size(); if (FrameIndex < 0 || NumBones*FrameIndex >= Frames.size()) { return false; } if (InverseVSIndices.empty()) { BuildInverseVSIndices(); } size_t NumVertices = VtxSrcIndices.size(); Positions.resize(3*NumVertices); // Set sizes: BoneMatrices.resize(NumBones); BoneStack.resize(NumBones); // Find which frame; remember that frame data comes in [NumBones] sets Model3D_Frame *FramePtr = &Frames[NumBones*FrameIndex]; Model3D_Frame *AddlFramePtr = &Frames[NumBones*AddlFrameIndex]; // Find the individual-bone transformation matrices: for (size_t ib=0; ib<NumBones; ib++) FindBoneTransform(BoneMatrices[ib],Bones[ib], FramePtr[ib],MixFrac,AddlFramePtr[ib]); // Find the cumulative-bone transformation matrices: int StackIndx = -1; size_t Parent = UNONE; for (unsigned int ib=0; ib<NumBones; ib++) { Model3D_Bone& Bone = Bones[ib]; // Do the pop-push with the stack // to get the bone's parent bone if (TEST_FLAG(Bone.Flags,Model3D_Bone::Pop)) { if (StackIndx >= 0) { Parent = BoneStack[StackIndx--]; } else{ Parent = UNONE; } } if (TEST_FLAG(Bone.Flags,Model3D_Bone::Push)) { StackIndx = MAX(StackIndx,-1); BoneStack[++StackIndx] = Parent; } // Do the transform! if (Parent != UNONE) { Model3D_Transform Res; TMatMultiply(Res,BoneMatrices[Parent],BoneMatrices[ib]); obj_copy(BoneMatrices[ib],Res); } // Default: parent of next bone is current bone Parent = ib; } bool NormalsPresent = !NormSources.empty(); if (NormalsPresent) { Normals.resize(NormSources.size()); } for (unsigned ivs=0; ivs<VtxSources.size(); ivs++) { Model3D_VertexSource& VS = VtxSources[ivs]; GLfloat Position[3]; if (VS.Bone0 >= 0) { Model3D_Transform& T0 = BoneMatrices[VS.Bone0]; TransformPoint(Position,VS.Position,T0); if (NormalsPresent) { for (int iv=InvVSIPointers[ivs]; iv<InvVSIPointers[ivs+1]; iv++) { int Indx = 3*InverseVSIndices[iv]; TransformVector(NormBase() + Indx, NormSrcBase() + Indx, T0); } } GLfloat Blend = VS.Blend; if (VS.Bone1 >= 0 && Blend != 0) { Model3D_Transform& T1 = BoneMatrices[VS.Bone1]; GLfloat PosExtra[3]; GLfloat PosDiff[3]; TransformPoint(PosExtra,VS.Position,T1); VecSub(PosExtra,Position,PosDiff); VecScalarMultTo(PosDiff,Blend); VecAddTo(Position,PosDiff); if (NormalsPresent) { for (int iv=InvVSIPointers[ivs]; iv<InvVSIPointers[ivs+1]; iv++) { int Indx = 3*InverseVSIndices[iv]; GLfloat NormExtra[3]; GLfloat NormDiff[3]; GLfloat *OrigNorm = NormSrcBase() + Indx; GLfloat *Norm = NormBase() + Indx; TransformVector(NormExtra,OrigNorm,T1); VecSub(NormExtra,Norm,NormDiff); VecScalarMultTo(NormDiff,Blend); VecAddTo(Norm,NormDiff); } } } } else // The assumed root bone (identity transformation) { VecCopy(VS.Position,Position); if (NormalsPresent) { for (int iv=InvVSIPointers[ivs]; iv<InvVSIPointers[ivs+1]; iv++) { int Indx = 3*InverseVSIndices[iv]; VecCopy(NormSrcBase() + Indx, NormBase() + Indx); } } } // Copy found position into vertex array! for (int iv=InvVSIPointers[ivs]; iv<InvVSIPointers[ivs+1]; iv++) VecCopy(Position,PosBase() + 3*InverseVSIndices[iv]); } if (UseModelTransform) { GLfloat *PP = PosBase(); for (size_t k=0; k<Positions.size()/3; k++, PP+=3) { GLfloat Position[3]; TransformPoint(Position,PP,TransformPos); VecCopy(Position,PP); } GLfloat *NP = NormBase(); for (size_t k=0; k<Normals.size()/3; k++, NP+=3) { GLfloat Normal[3]; TransformVector(Normal,NP,TransformNorm); VecCopy(Normal,NP); } } return true; }
FVector2D FGeometry::GetDrawSize() const { return TransformVector(GetAccumulatedLayoutTransform(), Size); }
bool Model3D::FindPositions_Sequence(bool UseModelTransform, GLshort SeqIndex, GLshort FrameIndex, GLfloat MixFrac, GLshort AddlFrameIndex) { // Bad inputs: do nothing and return false GLshort NumSF = NumSeqFrames(SeqIndex); if (NumSF <= 0) { return false; } if (FrameIndex < 0 || FrameIndex >= NumSF) { return false; } Model3D_Transform TSF; Model3D_SeqFrame& SF = SeqFrames[SeqFrmPointers[SeqIndex] + FrameIndex]; if (MixFrac != 0 && AddlFrameIndex != FrameIndex) { if (AddlFrameIndex < 0 || AddlFrameIndex >= NumSF) { return false; } Model3D_SeqFrame& ASF = SeqFrames[SeqFrmPointers[SeqIndex] + AddlFrameIndex]; FindFrameTransform(TSF,SF,MixFrac,ASF); if (!FindPositions_Frame(false,SF.Frame,MixFrac,ASF.Frame)) { return false; } } else { if (!FindPositions_Frame(false,SF.Frame)) { return false; } FindFrameTransform(TSF,SF,0,SF); } Model3D_Transform TTot; if (UseModelTransform) { TMatMultiply(TTot,TransformPos,TSF); } else{ obj_copy(TTot,TSF); } size_t NumVerts = Positions.size()/3; GLfloat *Pos = PosBase(); for (size_t iv=0; iv<NumVerts; iv++) { GLfloat NewPos[3]; TransformPoint(NewPos,Pos,TTot); VecCopy(NewPos,Pos); Pos += 3; } bool NormalsPresent = !NormSources.empty(); if (NormalsPresent) { // OK, since the bones don't change bulk if (UseModelTransform) { TMatMultiply(TTot,TransformNorm,TSF); } else{ obj_copy(TTot,TSF); } GLfloat *Norm = NormBase(); for (size_t iv=0; iv<NumVerts; iv++) { GLfloat NewNorm[3]; TransformVector(NewNorm,Norm,TTot); VecCopy(NewNorm,Norm); Norm += 3; } } return true; }
bool SCSM::BuildSRLocation(logoInfor &logoFeat) { // build point vector for (int i = 0; i < logoFeat.pointIndexofClusters.size(); ++i) { if (!logoFeat.pointIndexofClusters[i].empty()) { ObjKeywordNum onecenterinfor; onecenterinfor.logoName = logoFeat.baseinfor.logoName; onecenterinfor.num = logoFeat.pointIndexofClusters[i].size(); onecenterinfor.pointvec.reserve(onecenterinfor.num); onecenterinfor.allRSvec.reserve(mapnum); onecenterinfor.df = 1.0*onecenterinfor.num/logoFeat.keypointNum; for (int j = 0 ; j < onecenterinfor.num; j++) { KeyPoint keyloc = logoFeat.keypoints[logoFeat.pointIndexofClusters[i][j]]; // keyloc.pt.x = QuantizeLocation(keyloc.pt.x, logoFeat.baseinfor.width); // 量化坐标 // keyloc.pt.y = QuantizeLocation(keyloc.pt.y, logoFeat.baseinfor.height); // 量化坐标 onecenterinfor.pointvec.push_back(keyloc.pt); } onecenterinfor.clustercenter = i; objIfor.push_back(onecenterinfor); } } // compute different center to point vectors in different scales and rotations CvPoint orig_point, trans_point; CvPoint2D32f orig_vector, trans_vector; for (int i = 0; i < objIfor.size(); ++i) { // original scale and rotation ObjkeywdVec objkeywdlocation_orig; objkeywdlocation_orig.SR.rotation = 0; objkeywdlocation_orig.SR.scale = 1; objkeywdlocation_orig.pLocation.reserve(objIfor[i].num); objkeywdlocation_orig.PTCvec.reserve(objIfor[i].num); for (int j = 0; j < objIfor[i].num; j++) { orig_point = objIfor[i].pointvec[j]; TransformPoint(objkeywdlocation_orig.SR.rotation, objkeywdlocation_orig.SR.scale, orig_point, trans_point, trans_vector); objkeywdlocation_orig.pLocation.push_back(trans_point); objkeywdlocation_orig.PTCvec.push_back(trans_vector); } // other scales and rotations for (int j = 0; j < nQuantizedNS; ++j) { for (int k= 0; k < nQuantizedNR; ++k) { if (j == 2 && k == 0) { objIfor[i].allRSvec.push_back(objkeywdlocation_orig); continue; } ObjkeywdVec objkeywdlocation_other; objkeywdlocation_other.SR.rotation = k; objkeywdlocation_other.SR.scale = 0.5 + j/4.0; objkeywdlocation_other.pLocation.reserve(objIfor[i].num); objkeywdlocation_other.PTCvec.reserve(objIfor[i].num); for (int l = 0; l < objIfor[i].pointvec.size(); l++) { orig_vector = objkeywdlocation_orig.PTCvec[l]; TransformVector(objkeywdlocation_other.SR.rotation, objkeywdlocation_other.SR.scale, orig_vector, trans_point, trans_vector); objkeywdlocation_other.pLocation.push_back(trans_point); objkeywdlocation_other.PTCvec.push_back(trans_vector); } objIfor[i].allRSvec.push_back(objkeywdlocation_other); } } } return true; }