/* Clip a line against the viewport and user clip planes. */ static void do_clip_line( struct draw_stage *stage, struct prim_header *header, unsigned clipmask ) { const struct clip_stage *clipper = clip_stage( stage ); struct vertex_header *v0 = header->v[0]; struct vertex_header *v1 = header->v[1]; const float *pos0 = v0->clip; const float *pos1 = v1->clip; float t0 = 0.0F; float t1 = 0.0F; struct prim_header newprim; while (clipmask) { const unsigned plane_idx = ffs(clipmask)-1; const float *plane = clipper->plane[plane_idx]; const float dp0 = dot4( pos0, plane ); const float dp1 = dot4( pos1, plane ); if (dp1 < 0.0F) { float t = dp1 / (dp1 - dp0); t1 = MAX2(t1, t); } if (dp0 < 0.0F) { float t = dp0 / (dp0 - dp1); t0 = MAX2(t0, t); } if (t0 + t1 >= 1.0F) return; /* discard */ clipmask &= ~(1 << plane_idx); /* turn off this plane's bit */ } if (v0->clipmask) { interp( clipper, stage->tmp[0], t0, v0, v1 ); if (clipper->flat) copy_colors(stage, stage->tmp[0], v0); newprim.v[0] = stage->tmp[0]; } else { newprim.v[0] = v0; } if (v1->clipmask) { interp( clipper, stage->tmp[1], t1, v1, v0 ); newprim.v[1] = stage->tmp[1]; } else { newprim.v[1] = v1; } stage->next->line( stage->next, &newprim ); }
inline Nimble::Vector3T<T> operator*(const Nimble::Vector3T<T>& m2, const Nimble::Matrix4T<T>& m1) { Nimble::Vector3T<T> res; for(int i = 0; i < 3; i++) res[i] = dot4(m1.column(i),m2); return res; }
static INLINE unsigned compute_clipmask_gl(const float *clip, /*const*/ float plane[][4], unsigned nr) { unsigned mask = 0x0; unsigned i; #if 0 debug_printf("compute clipmask %f %f %f %f\n", clip[0], clip[1], clip[2], clip[3]); assert(clip[3] != 0.0); #endif /* Do the hardwired planes first: */ if (-clip[0] + clip[3] < 0) mask |= (1<<0); if ( clip[0] + clip[3] < 0) mask |= (1<<1); if (-clip[1] + clip[3] < 0) mask |= (1<<2); if ( clip[1] + clip[3] < 0) mask |= (1<<3); if ( clip[2] + clip[3] < 0) mask |= (1<<4); /* match mesa clipplane numbering - for now */ if (-clip[2] + clip[3] < 0) mask |= (1<<5); /* match mesa clipplane numbering - for now */ /* Followed by any remaining ones: */ for (i = 6; i < nr; i++) { if (dot4(clip, plane[i]) < 0) mask |= (1<<i); } return mask; }
void GasTransport::updateDiff_T() { update_T(); // evaluate binary diffusion coefficients at unit pressure size_t ic = 0; if (m_mode == CK_Mode) { for (size_t i = 0; i < m_nsp; i++) { for (size_t j = i; j < m_nsp; j++) { m_bdiff(i,j) = exp(dot4(m_polytempvec, m_diffcoeffs[ic])); m_bdiff(j,i) = m_bdiff(i,j); ic++; } } } else { for (size_t i = 0; i < m_nsp; i++) { for (size_t j = i; j < m_nsp; j++) { m_bdiff(i,j) = m_temp * m_sqrt_t*dot5(m_polytempvec, m_diffcoeffs[ic]); m_bdiff(j,i) = m_bdiff(i,j); ic++; } } } m_bindiff_ok = true; }
void matrixVector4(int X[4][4], int y[4], int z[4]) { int i; for (i = 0; i < 4; i++) { z[i] = dot4(X[i], y); } }
/** * Update the binary diffusion coefficients. These are evaluated * from the polynomial fits at unit pressure (1 Pa). */ void LiquidTransport::updateDiff_temp() { // evaluate binary diffusion coefficients at unit pressure int i,j; int ic = 0; if (m_mode == CK_Mode) { for (i = 0; i < m_nsp; i++) { for (j = i; j < m_nsp; j++) { m_bdiff(i,j) = exp(dot4(m_polytempvec, m_diffcoeffs[ic])); m_bdiff(j,i) = m_bdiff(i,j); ic++; } } } else { for (i = 0; i < m_nsp; i++) { for (j = i; j < m_nsp; j++) { m_bdiff(i,j) = m_temp * m_sqrt_t*dot5(m_polytempvec, m_diffcoeffs[ic]); m_bdiff(j,i) = m_bdiff(i,j); ic++; } } } m_diff_temp_ok = true; m_diff_mix_ok = false; }
void AqueousTransport::updateCond_T() { if (m_mode == CK_Mode) { for (size_t k = 0; k < m_nsp; k++) { m_cond[k] = exp(dot4(m_polytempvec, m_condcoeffs[k])); } } else { for (size_t k = 0; k < m_nsp; k++) { m_cond[k] = m_sqrt_t*dot5(m_polytempvec, m_condcoeffs[k]); } } m_spcond_ok = true; m_condmix_ok = false; }
/** * Update the temperature-dependent parts of the mixture-averaged * thermal conductivity. */ void LiquidTransport::updateCond_temp() { int k; if (m_mode == CK_Mode) { for (k = 0; k < m_nsp; k++) { m_cond[k] = exp(dot4(m_polytempvec, m_condcoeffs[k])); } } else { for (k = 0; k < m_nsp; k++) { m_cond[k] = m_sqrt_t * dot5(m_polytempvec, m_condcoeffs[k]); } } m_cond_temp_ok = true; m_cond_mix_ok = false; }
void AqueousTransport::updateSpeciesViscosities() { if (m_mode == CK_Mode) { for (size_t k = 0; k < m_nsp; k++) { m_visc[k] = exp(dot4(m_polytempvec, m_visccoeffs[k])); m_sqvisc[k] = sqrt(m_visc[k]); } } else { for (size_t k = 0; k < m_nsp; k++) { // the polynomial fit is done for sqrt(visc/sqrt(T)) m_sqvisc[k] = m_t14*dot5(m_polytempvec, m_visccoeffs[k]); m_visc[k] = (m_sqvisc[k]*m_sqvisc[k]); } } m_spvisc_ok = true; }
/* * this function extracts the clip distance for the current plane, * it first checks if the shader provided a clip distance, otherwise * it works out the value using the clipvertex */ static inline float getclipdist(const struct clip_stage *clipper, struct vertex_header *vert, int plane_idx) { const float *plane; float dp; if (vert->have_clipdist && plane_idx >= 6) { /* pick the correct clipdistance element from the output vectors */ int _idx = plane_idx - 6; int cdi = _idx >= 4; int vidx = cdi ? _idx - 4 : _idx; dp = vert->data[draw_current_shader_clipdistance_output(clipper->stage.draw, cdi)][vidx]; } else { plane = clipper->plane[plane_idx]; dp = dot4(vert->clip, plane); } return dp; }
static int luaB_dot (lua_State *L) { float x1, y1, z1, w1; float x2, y2, z2, w2; if (lua_gettop(L) != 2) luaL_error(L, "Invalid params, try dot(v,v)"); if (lua_isvector4(L,1)) { lua_checkvector4(L, 1, &x1, &y1, &z1, &w1); lua_checkvector4(L, 2, &x2, &y2, &z2, &w2); lua_pushnumber(L,dot4(x1,y1,z1,w1, x2,y2,z2,w2)); } else if (lua_isvector3(L,1)) { lua_checkvector3(L, 1, &x1, &y1, &z1); lua_checkvector3(L, 2, &x2, &y2, &z2); lua_pushnumber(L,dot3(x1,y1,z1, x2,y2,z2)); } else if (lua_isvector2(L,1)) { lua_checkvector2(L, 1, &x1, &y1); lua_checkvector2(L, 2, &x2, &y2); lua_pushnumber(L,dot2(x1,y1, x2,y2)); } return 1; }
bool BSP::isInOpenSpaceSSE(const vec3 &pos) const { if (top != NULL){ v4sf zero = setzerops(); v4sf pos4 = loadups((const float *) &vec4(pos, 1)); SSENode *node = sseTop; while (true){ v4sf d = dot4(node->tri.plane, pos4); if (comigt(d, zero)){ if (node->front){ node = node->front; } else return true; } else { if (node->back){ node = node->back; } else return false; } } } return false; }
/** * Update the temperature-dependent viscosity terms. * Updates the array of pure species viscosities, and the * weighting functions in the viscosity mixture rule. * The flag m_visc_ok is set to true. */ void LiquidTransport::updateViscosity_temp() { int k; doublereal vratiokj, wratiojk, factor1; if (m_mode == CK_Mode) { for (k = 0; k < m_nsp; k++) { viscSpecies_[k] = exp(dot4(m_polytempvec, viscCoeffsVector_[k])); m_sqvisc[k] = sqrt(viscSpecies_[k]); } } else { for (k = 0; k < m_nsp; k++) { // the polynomial fit is done for sqrt(visc/sqrt(T)) m_sqvisc[k] = m_t14*dot5(m_polytempvec, viscCoeffsVector_[k]); viscSpecies_[k] = (m_sqvisc[k]*m_sqvisc[k]); } } // see Eq. (9-5.15) of Reid, Prausnitz, and Poling int j; for (j = 0; j < m_nsp; j++) { for (k = j; k < m_nsp; k++) { vratiokj = viscSpecies_[k]/viscSpecies_[j]; wratiojk = m_mw[j]/m_mw[k]; // Note that m_wratjk(k,j) holds the square root of // m_wratjk(j,k)! factor1 = 1.0 + (m_sqvisc[k]/m_sqvisc[j]) * m_wratjk(k,j); m_phi(k,j) = factor1*factor1 / (SqrtEight * m_wratkj1(j,k)); m_phi(j,k) = m_phi(k,j)/(vratiokj * wratiojk); } } m_visc_temp_ok = true; m_visc_mix_ok = false; }
double V4::angle(V4 const& rhs) const{ //theta = arccos((a.dot3(b))/(a.module()*b.module()) return acos(dot4(rhs)/(module()*rhs.module())); }
/* Clip a triangle against the viewport and user clip planes. */ static void do_clip_tri( struct draw_stage *stage, struct prim_header *header, unsigned clipmask ) { struct clip_stage *clipper = clip_stage( stage ); struct vertex_header *a[MAX_CLIPPED_VERTICES]; struct vertex_header *b[MAX_CLIPPED_VERTICES]; struct vertex_header **inlist = a; struct vertex_header **outlist = b; unsigned tmpnr = 0; unsigned n = 3; unsigned i; boolean aEdges[MAX_CLIPPED_VERTICES]; boolean bEdges[MAX_CLIPPED_VERTICES]; boolean *inEdges = aEdges; boolean *outEdges = bEdges; inlist[0] = header->v[0]; inlist[1] = header->v[1]; inlist[2] = header->v[2]; /* * Note: at this point we can't just use the per-vertex edge flags. * We have to observe the edge flag bits set in header->flags which * were set during primitive decomposition. Put those flags into * an edge flags array which parallels the vertex array. * Later, in the 'unfilled' pipeline stage we'll draw the edge if both * the header.flags bit is set AND the per-vertex edgeflag field is set. */ inEdges[0] = !!(header->flags & DRAW_PIPE_EDGE_FLAG_0); inEdges[1] = !!(header->flags & DRAW_PIPE_EDGE_FLAG_1); inEdges[2] = !!(header->flags & DRAW_PIPE_EDGE_FLAG_2); while (clipmask && n >= 3) { const unsigned plane_idx = ffs(clipmask)-1; const boolean is_user_clip_plane = plane_idx >= 6; const float *plane = clipper->plane[plane_idx]; struct vertex_header *vert_prev = inlist[0]; boolean *edge_prev = &inEdges[0]; float dp_prev = dot4( vert_prev->clip, plane ); unsigned outcount = 0; clipmask &= ~(1<<plane_idx); assert(n < MAX_CLIPPED_VERTICES); if (n >= MAX_CLIPPED_VERTICES) return; inlist[n] = inlist[0]; /* prevent rotation of vertices */ inEdges[n] = inEdges[0]; for (i = 1; i <= n; i++) { struct vertex_header *vert = inlist[i]; boolean *edge = &inEdges[i]; float dp = dot4( vert->clip, plane ); if (!IS_NEGATIVE(dp_prev)) { assert(outcount < MAX_CLIPPED_VERTICES); if (outcount >= MAX_CLIPPED_VERTICES) return; outEdges[outcount] = *edge_prev; outlist[outcount++] = vert_prev; } if (DIFFERENT_SIGNS(dp, dp_prev)) { struct vertex_header *new_vert; boolean *new_edge; assert(tmpnr < MAX_CLIPPED_VERTICES + 1); if (tmpnr >= MAX_CLIPPED_VERTICES + 1) return; new_vert = clipper->stage.tmp[tmpnr++]; assert(outcount < MAX_CLIPPED_VERTICES); if (outcount >= MAX_CLIPPED_VERTICES) return; new_edge = &outEdges[outcount]; outlist[outcount++] = new_vert; if (IS_NEGATIVE(dp)) { /* Going out of bounds. Avoid division by zero as we * know dp != dp_prev from DIFFERENT_SIGNS, above. */ float t = dp / (dp - dp_prev); interp( clipper, new_vert, t, vert, vert_prev ); /* Whether or not to set edge flag for the new vert depends * on whether it's a user-defined clipping plane. We're * copying NVIDIA's behaviour here. */ if (is_user_clip_plane) { /* we want to see an edge along the clip plane */ *new_edge = TRUE; new_vert->edgeflag = TRUE; } else { /* we don't want to see an edge along the frustum clip plane */ *new_edge = *edge_prev; new_vert->edgeflag = FALSE; } } else { /* Coming back in. */ float t = dp_prev / (dp_prev - dp); interp( clipper, new_vert, t, vert_prev, vert ); /* Copy starting vert's edgeflag: */ new_vert->edgeflag = vert_prev->edgeflag; *new_edge = *edge_prev; } } vert_prev = vert; edge_prev = edge; dp_prev = dp; } /* swap in/out lists */ { struct vertex_header **tmp = inlist; inlist = outlist; outlist = tmp; n = outcount; } { boolean *tmp = inEdges; inEdges = outEdges; outEdges = tmp; } } /* If flat-shading, copy provoking vertex color to polygon vertex[0] */ if (n >= 3) { if (clipper->flat) { if (stage->draw->rasterizer->flatshade_first) { if (inlist[0] != header->v[0]) { assert(tmpnr < MAX_CLIPPED_VERTICES + 1); if (tmpnr >= MAX_CLIPPED_VERTICES + 1) return; inlist[0] = dup_vert(stage, inlist[0], tmpnr++); copy_colors(stage, inlist[0], header->v[0]); } } else { if (inlist[0] != header->v[2]) { assert(tmpnr < MAX_CLIPPED_VERTICES + 1); if (tmpnr >= MAX_CLIPPED_VERTICES + 1) return; inlist[0] = dup_vert(stage, inlist[0], tmpnr++); copy_colors(stage, inlist[0], header->v[2]); } } } /* Emit the polygon as triangles to the setup stage: */ emit_poly( stage, inlist, inEdges, n, header ); } }
float noise4(float x, float y, float z, float w) { float noise[5] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f}; float s = (x + y + z + w) * F4; float i = floorf(x + s); float j = floorf(y + s); float k = floorf(z + s); float l = floorf(w + s); float t = (i + j + k + l) * G4; float x0 = x - (i - t); float y0 = y - (j - t); float z0 = z - (k - t); float w0 = w - (l - t); int c = (x0 > y0)*32 + (x0 > z0)*16 + (y0 > z0)*8 + (x0 > w0)*4 + (y0 > w0)*2 + (z0 > w0); int i1 = SIMPLEX[c][0]>=3; int j1 = SIMPLEX[c][1]>=3; int k1 = SIMPLEX[c][2]>=3; int l1 = SIMPLEX[c][3]>=3; int i2 = SIMPLEX[c][0]>=2; int j2 = SIMPLEX[c][1]>=2; int k2 = SIMPLEX[c][2]>=2; int l2 = SIMPLEX[c][3]>=2; int i3 = SIMPLEX[c][0]>=1; int j3 = SIMPLEX[c][1]>=1; int k3 = SIMPLEX[c][2]>=1; int l3 = SIMPLEX[c][3]>=1; float x1 = x0 - i1 + G4; float y1 = y0 - j1 + G4; float z1 = z0 - k1 + G4; float w1 = w0 - l1 + G4; float x2 = x0 - i2 + 2.0f*G4; float y2 = y0 - j2 + 2.0f*G4; float z2 = z0 - k2 + 2.0f*G4; float w2 = w0 - l2 + 2.0f*G4; float x3 = x0 - i3 + 3.0f*G4; float y3 = y0 - j3 + 3.0f*G4; float z3 = z0 - k3 + 3.0f*G4; float w3 = w0 - l3 + 3.0f*G4; float x4 = x0 - 1.0f + 4.0f*G4; float y4 = y0 - 1.0f + 4.0f*G4; float z4 = z0 - 1.0f + 4.0f*G4; float w4 = w0 - 1.0f + 4.0f*G4; int I = (int)i & 255; int J = (int)j & 255; int K = (int)k & 255; int L = (int)l & 255; int gi0 = PERM[I + PERM[J + PERM[K + PERM[L]]]] & 0x1f; int gi1 = PERM[I + i1 + PERM[J + j1 + PERM[K + k1 + PERM[L + l1]]]] & 0x1f; int gi2 = PERM[I + i2 + PERM[J + j2 + PERM[K + k2 + PERM[L + l2]]]] & 0x1f; int gi3 = PERM[I + i3 + PERM[J + j3 + PERM[K + k3 + PERM[L + l3]]]] & 0x1f; int gi4 = PERM[I + 1 + PERM[J + 1 + PERM[K + 1 + PERM[L + 1]]]] & 0x1f; float t0, t1, t2, t3, t4; t0 = 0.6f - x0*x0 - y0*y0 - z0*z0 - w0*w0; if (t0 >= 0.0f) { t0 *= t0; noise[0] = t0 * t0 * dot4(GRAD4[gi0], x0, y0, z0, w0); } t1 = 0.6f - x1*x1 - y1*y1 - z1*z1 - w1*w1; if (t1 >= 0.0f) { t1 *= t1; noise[1] = t1 * t1 * dot4(GRAD4[gi1], x1, y1, z1, w1); } t2 = 0.6f - x2*x2 - y2*y2 - z2*z2 - w2*w2; if (t2 >= 0.0f) { t2 *= t2; noise[2] = t2 * t2 * dot4(GRAD4[gi2], x2, y2, z2, w2); } t3 = 0.6f - x3*x3 - y3*y3 - z3*z3 - w3*w3; if (t3 >= 0.0f) { t3 *= t3; noise[3] = t3 * t3 * dot4(GRAD4[gi3], x3, y3, z3, w3); } t4 = 0.6f - x4*x4 - y4*y4 - z4*z4 - w4*w4; if (t4 >= 0.0f) { t4 *= t4; noise[4] = t4 * t4 * dot4(GRAD4[gi4], x4, y4, z4, w4); } return 27.0 * (noise[0] + noise[1] + noise[2] + noise[3] + noise[4]); }
float simplexRawNoise4( const float x, const float y, const float z, const float w ) { float F4 = (sqrtf(5.0)-1.0)/4.0; float G4 = (5.0-sqrtf(5.0))/20.0; float n0, n1, n2, n3, n4; float s = (x + y + z + w) * F4; int i = fastfloor(x + s); int j = fastfloor(y + s); int k = fastfloor(z + s); int l = fastfloor(w + s); float t = (i + j + k + l) * G4; float X0 = i - t; float Y0 = j - t; float Z0 = k - t; float W0 = l - t; float x0 = x - X0; float y0 = y - Y0; float z0 = z - Z0; float w0 = w - W0; int c1 = (x0 > y0) ? 32 : 0; int c2 = (x0 > z0) ? 16 : 0; int c3 = (y0 > z0) ? 8 : 0; int c4 = (x0 > w0) ? 4 : 0; int c5 = (y0 > w0) ? 2 : 0; int c6 = (z0 > w0) ? 1 : 0; int c = c1 + c2 + c3 + c4 + c5 + c6; int i1, j1, k1, l1; int i2, j2, k2, l2; int i3, j3, k3, l3; i1 = simplex[c][0]>=3 ? 1 : 0; j1 = simplex[c][1]>=3 ? 1 : 0; k1 = simplex[c][2]>=3 ? 1 : 0; l1 = simplex[c][3]>=3 ? 1 : 0; i2 = simplex[c][0]>=2 ? 1 : 0; j2 = simplex[c][1]>=2 ? 1 : 0; k2 = simplex[c][2]>=2 ? 1 : 0; l2 = simplex[c][3]>=2 ? 1 : 0; i3 = simplex[c][0]>=1 ? 1 : 0; j3 = simplex[c][1]>=1 ? 1 : 0; k3 = simplex[c][2]>=1 ? 1 : 0; l3 = simplex[c][3]>=1 ? 1 : 0; float x1 = x0 - i1 + G4; float y1 = y0 - j1 + G4; float z1 = z0 - k1 + G4; float w1 = w0 - l1 + G4; float x2 = x0 - i2 + 2.0*G4; float y2 = y0 - j2 + 2.0*G4; float z2 = z0 - k2 + 2.0*G4; float w2 = w0 - l2 + 2.0*G4; float x3 = x0 - i3 + 3.0*G4; float y3 = y0 - j3 + 3.0*G4; float z3 = z0 - k3 + 3.0*G4; float w3 = w0 - l3 + 3.0*G4; float x4 = x0 - 1.0 + 4.0*G4; float y4 = y0 - 1.0 + 4.0*G4; float z4 = z0 - 1.0 + 4.0*G4; float w4 = w0 - 1.0 + 4.0*G4; int ii = i & 255; int jj = j & 255; int kk = k & 255; int ll = l & 255; int gi0 = perm[ii+perm[jj+perm[kk+perm[ll]]]] % 32; int gi1 = perm[ii+i1+perm[jj+j1+perm[kk+k1+perm[ll+l1]]]] % 32; int gi2 = perm[ii+i2+perm[jj+j2+perm[kk+k2+perm[ll+l2]]]] % 32; int gi3 = perm[ii+i3+perm[jj+j3+perm[kk+k3+perm[ll+l3]]]] % 32; int gi4 = perm[ii+1+perm[jj+1+perm[kk+1+perm[ll+1]]]] % 32; float t0 = 0.6 - x0*x0 - y0*y0 - z0*z0 - w0*w0; if(t0<0) n0 = 0.0; else { t0 *= t0; n0 = t0 * t0 * dot4(grad4[gi0], x0, y0, z0, w0); } float t1 = 0.6 - x1*x1 - y1*y1 - z1*z1 - w1*w1; if(t1<0) n1 = 0.0; else { t1 *= t1; n1 = t1 * t1 * dot4(grad4[gi1], x1, y1, z1, w1); } float t2 = 0.6 - x2*x2 - y2*y2 - z2*z2 - w2*w2; if(t2<0) n2 = 0.0; else { t2 *= t2; n2 = t2 * t2 * dot4(grad4[gi2], x2, y2, z2, w2); } float t3 = 0.6 - x3*x3 - y3*y3 - z3*z3 - w3*w3; if(t3<0) n3 = 0.0; else { t3 *= t3; n3 = t3 * t3 * dot4(grad4[gi3], x3, y3, z3, w3); } float t4 = 0.6 - x4*x4 - y4*y4 - z4*z4 - w4*w4; if(t4<0) n4 = 0.0; else { t4 *= t4; n4 = t4 * t4 * dot4(grad4[gi4], x4, y4, z4, w4); } return 27.0 * (n0 + n1 + n2 + n3 + n4); }
// 4D simplex noise float simplexnoise( float x, float y, float z, float w ) { // The skewing and unskewing factors are hairy again for the 4D case const float F4 = ( sqrt( 5.0 ) - 1.0 ) / 4.0; const float G4 = ( 5.0 - sqrt( 5.0 ) ) / 20.0; float n0, n1, n2, n3, n4; // Noise contributions from the five corners // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in float s = ( x + y + z + w ) * F4; // Factor for 4D skewing int i = floor( x + s ); int j = floor( y + s ); int k = floor( z + s ); int l = floor( w + s ); float t = ( i + j + k + l ) * G4; // Factor for 4D unskewing float X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space float Y0 = j - t; float Z0 = k - t; float W0 = l - t; float x0 = x - X0; // The x,y,z,w distances from the cell origin float y0 = y - Y0; float z0 = z - Z0; float w0 = w - W0; // For the 4D case, the simplex is a 4D shape I won't even try to describe. // To find out which of the 24 possible simplices we're in, we need to // determine the magnitude ordering of x0, y0, z0 and w0. // The method below is a good way of finding the ordering of x,y,z,w and // then find the correct traversal order for the simplex were in. // First, six pair-wise comparisons are performed between each possible pair // of the four coordinates, and the results are used to add up binary bits // for an integer index. int c1 = ( x0 > y0 ) ? 32 : 0; int c2 = ( x0 > z0 ) ? 16 : 0; int c3 = ( y0 > z0 ) ? 8 : 0; int c4 = ( x0 > w0 ) ? 4 : 0; int c5 = ( y0 > w0 ) ? 2 : 0; int c6 = ( z0 > w0 ) ? 1 : 0; int c = c1 + c2 + c3 + c4 + c5 + c6; int i1, j1, k1, l1; // The integer offsets for the second simplex corner int i2, j2, k2, l2; // The integer offsets for the third simplex corner int i3, j3, k3, l3; // The integer offsets for the fourth simplex corner // simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order. // Many values of c will never occur, since e.g. x>y>z>w makes x<z, y<w and x<w // impossible. Only the 24 indices which have non-zero entries make any sense. // We use a thresholding to set the coordinates in turn from the largest magnitude. // The number 3 in the "simplex" array is at the position of the largest coordinate. i1 = simplex[c][0] >= 3 ? 1 : 0; j1 = simplex[c][1] >= 3 ? 1 : 0; k1 = simplex[c][2] >= 3 ? 1 : 0; l1 = simplex[c][3] >= 3 ? 1 : 0; // The number 2 in the "simplex" array is at the second largest coordinate. i2 = simplex[c][0] >= 2 ? 1 : 0; j2 = simplex[c][1] >= 2 ? 1 : 0; k2 = simplex[c][2] >= 2 ? 1 : 0; l2 = simplex[c][3] >= 2 ? 1 : 0; // The number 1 in the "simplex" array is at the second smallest coordinate. i3 = simplex[c][0] >= 1 ? 1 : 0; j3 = simplex[c][1] >= 1 ? 1 : 0; k3 = simplex[c][2] >= 1 ? 1 : 0; l3 = simplex[c][3] >= 1 ? 1 : 0; // The fifth corner has all coordinate offsets = 1, so no need to look that up. float x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords float y1 = y0 - j1 + G4; float z1 = z0 - k1 + G4; float w1 = w0 - l1 + G4; float x2 = x0 - i2 + 2.0 * G4; // Offsets for third corner in (x,y,z,w) coords float y2 = y0 - j2 + 2.0 * G4; float z2 = z0 - k2 + 2.0 * G4; float w2 = w0 - l2 + 2.0 * G4; float x3 = x0 - i3 + 3.0 * G4; // Offsets for fourth corner in (x,y,z,w) coords float y3 = y0 - j3 + 3.0 * G4; float z3 = z0 - k3 + 3.0 * G4; float w3 = w0 - l3 + 3.0 * G4; float x4 = x0 - 1.0 + 4.0 * G4; // Offsets for last corner in (x,y,z,w) coords float y4 = y0 - 1.0 + 4.0 * G4; float z4 = z0 - 1.0 + 4.0 * G4; float w4 = w0 - 1.0 + 4.0 * G4; // Work out the hashed gradient indices of the five simplex corners int ii = i & 255; int jj = j & 255; int kk = k & 255; int ll = l & 255; int gi0 = perm[ii + perm[jj + perm[kk + perm[ll]]]] % 32; int gi1 = perm[ii + i1 + perm[jj + j1 + perm[kk + k1 + perm[ll + l1]]]] % 32; int gi2 = perm[ii + i2 + perm[jj + j2 + perm[kk + k2 + perm[ll + l2]]]] % 32; int gi3 = perm[ii + i3 + perm[jj + j3 + perm[kk + k3 + perm[ll + l3]]]] % 32; int gi4 = perm[ii + 1 + perm[jj + 1 + perm[kk + 1 + perm[ll + 1]]]] % 32; // Calculate the contribution from the five corners float t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0; if( t0 < 0 ) n0 = 0.0; else { t0 *= t0; n0 = t0 * t0 * dot4( grad4[gi0], x0, y0, z0, w0 ); } float t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1; if( t1 < 0 ) n1 = 0.0; else { t1 *= t1; n1 = t1 * t1 * dot4( grad4[gi1], x1, y1, z1, w1 ); } float t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2; if( t2 < 0 ) n2 = 0.0; else { t2 *= t2; n2 = t2 * t2 * dot4( grad4[gi2], x2, y2, z2, w2 ); } float t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3; if( t3 < 0 ) n3 = 0.0; else { t3 *= t3; n3 = t3 * t3 * dot4( grad4[gi3], x3, y3, z3, w3 ); } float t4 = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4; if( t4 < 0 ) n4 = 0.0; else { t4 *= t4; n4 = t4 * t4 * dot4( grad4[gi4], x4, y4, z4, w4 ); } // Sum up and scale the result to cover the range [-1,1] return 27.0 * ( n0 + n1 + n2 + n3 + n4 ); }
float vec4Len(const vec4& v) { return sqrt(dot4(v ,v)); }
/* Clip a triangle against the viewport and user clip planes. */ static void do_clip_tri( struct draw_stage *stage, struct prim_header *header, unsigned clipmask ) { struct clipper *clipper = clipper_stage( stage ); struct vertex_header *a[MAX_CLIPPED_VERTICES]; struct vertex_header *b[MAX_CLIPPED_VERTICES]; struct vertex_header **inlist = a; struct vertex_header **outlist = b; unsigned tmpnr = 0; unsigned n = 3; unsigned i; inlist[0] = header->v[0]; inlist[1] = header->v[1]; inlist[2] = header->v[2]; while (clipmask && n >= 3) { const unsigned plane_idx = ffs(clipmask)-1; const float *plane = clipper->plane[plane_idx]; struct vertex_header *vert_prev = inlist[0]; float dp_prev = dot4( vert_prev->clip, plane ); unsigned outcount = 0; clipmask &= ~(1<<plane_idx); inlist[n] = inlist[0]; /* prevent rotation of vertices */ for (i = 1; i <= n; i++) { struct vertex_header *vert = inlist[i]; float dp = dot4( vert->clip, plane ); if (!IS_NEGATIVE(dp_prev)) { outlist[outcount++] = vert_prev; } if (DIFFERENT_SIGNS(dp, dp_prev)) { struct vertex_header *new_vert = clipper->stage.tmp[tmpnr++]; outlist[outcount++] = new_vert; if (IS_NEGATIVE(dp)) { /* Going out of bounds. Avoid division by zero as we * know dp != dp_prev from DIFFERENT_SIGNS, above. */ float t = dp / (dp - dp_prev); interp( clipper, new_vert, t, vert, vert_prev ); /* Force edgeflag true in this case: */ new_vert->edgeflag = 1; } else { /* Coming back in. */ float t = dp_prev / (dp_prev - dp); interp( clipper, new_vert, t, vert_prev, vert ); /* Copy starting vert's edgeflag: */ new_vert->edgeflag = vert_prev->edgeflag; } } vert_prev = vert; dp_prev = dp; } { struct vertex_header **tmp = inlist; inlist = outlist; outlist = tmp; n = outcount; } } /* If flat-shading, copy color to new provoking vertex. */ if (clipper->flat && inlist[0] != header->v[2]) { if (1) { inlist[0] = dup_vert(stage, inlist[0], tmpnr++); } copy_colors(stage, inlist[0], header->v[2]); } /* Emit the polygon as triangles to the setup stage: */ if (n >= 3) emit_poly( stage, inlist, n, header ); }