/* g in Z[X] potentially defines a subfield of Q[X]/f. It is a subfield iff A * (cf subfield) was a block system; then there * exists h in Q[X] such that f | g o h. listdelta determines h s.t f | g o h * in Fp[X] (cf chinese_retrieve_pol). Try to lift it; den is a * multiplicative bound for denominator of lift. */ static GEN embedding(GEN g, GEN DATA, primedata *S, GEN den, GEN listdelta) { GEN TR, w0_Q, w0, w1_Q, w1, wpow, h0, gp, T, q2, q, maxp, a, p = S->p; long rt; pari_sp av; T = gel(DATA,1); rt = brent_kung_optpow(degpol(T), 2); maxp= gel(DATA,7); gp = derivpol(g); av = avma; w0 = chinese_retrieve_pol(DATA, S, listdelta); w0_Q = centermod(gmul(w0,den), p); h0 = FpXQ_inv(FpX_FpXQ_compo(gp,w0, T,p), T,p); /* = 1/g'(w0) mod (T,p) */ wpow = NULL; q = sqri(p); for(;;) {/* Given g,w0,h0 in Z[x], s.t. h0.g'(w0) = 1 and g(w0) = 0 mod (T,p), find * [w1,h1] satisfying the same conditions mod p^2, [w1,h1] = [w0,h0] (mod p) * (cf. Dixon: J. Austral. Math. Soc., Series A, vol.49, 1990, p.445) */ if (DEBUGLEVEL>1) fprintferr("lifting embedding mod p^k = %Z^%ld\n",p, Z_pval(q,p)); /* w1 := w0 - h0 g(w0) mod (T,q) */ if (wpow) a = FpX_FpXQV_compo(g,wpow, T,q); else a = FpX_FpXQ_compo(g,w0, T,q); /* first time */ /* now, a = 0 (p) */ a = gmul(gneg(h0), gdivexact(a, p)); w1 = gadd(w0, gmul(p, FpX_rem(a, T,p))); w1_Q = centermod(gmul(w1, remii(den,q)), q); if (gequal(w1_Q, w0_Q) || cmpii(q,maxp) > 0) { GEN G = gcmp1(den)? g: RgX_rescale(g,den); if (gcmp0(RgX_RgXQ_compo(G, w1_Q, T))) break; } if (cmpii(q, maxp) > 0) { if (DEBUGLEVEL) fprintferr("coeff too big for embedding\n"); return NULL; } gerepileall(av, 5, &w1,&h0,&w1_Q,&q,&p); q2 = sqri(q); wpow = FpXQ_powers(w1, rt, T, q2); /* h0 := h0 * (2 - h0 g'(w1)) mod (T,q) * = h0 + h0 * (1 - h0 g'(w1)) */ a = gmul(gneg(h0), FpX_FpXQV_compo(gp, FpXV_red(wpow,q),T,q)); a = ZX_Z_add(FpX_rem(a, T,q), gen_1); /* 1 - h0 g'(w1) = 0 (p) */ a = gmul(h0, gdivexact(a, p)); h0 = gadd(h0, gmul(p, FpX_rem(a, T,p))); w0 = w1; w0_Q = w1_Q; p = q; q = q2; } TR = gel(DATA,5); if (!gcmp0(TR)) w1_Q = translate_pol(w1_Q, TR); return gdiv(w1_Q,den); }
static GEN sqrconst(GEN pol, Red *R) { GEN z = cgetg(3,t_POL); gel(z,2) = centermodii(sqri(gel(pol,2)), R->N, R->N2); z[1] = pol[1]; return z; }
static GEN F2xq_elltrace_Harley(GEN a6, GEN T2) { pari_sp ltop = avma; pari_timer ti; GEN T, sqx; GEN x, x2, t; long n = F2x_degree(T2), N = ((n + 1)>>1) + 2; long ispcyc; if (n==1) return gen_m1; if (n==2) return F2x_degree(a6) ? gen_1 : stoi(-3); if (n==3) return F2x_degree(a6) ? (F2xq_trace(a6,T2) ? stoi(-3): gen_1) : stoi(5); timer_start(&ti); sqx = mkvec2(F2xq_sqrt(polx_F2x(T2[1]),T2), T2); if (DEBUGLEVEL>1) timer_printf(&ti,"Sqrtx"); ispcyc = zx_is_pcyc(F2x_to_Flx(T2)); T = ispcyc? F2x_to_ZX(T2): F2x_canonlift(T2, N-2); if (DEBUGLEVEL>1) timer_printf(&ti,"Teich"); T = FpX_get_red(T, int2n(N)); if (DEBUGLEVEL>1) timer_printf(&ti,"Barrett"); x = solve_AGM_eqn(F2x_to_ZX(a6), N-2, T, sqx); if (DEBUGLEVEL>1) timer_printf(&ti,"Lift"); x2 = ZX_Z_add_shallow(ZX_shifti(x,2), gen_1); t = (ispcyc? Z2XQ_invnorm_pcyc: Z2XQ_invnorm)(x2, T, N); if (DEBUGLEVEL>1) timer_printf(&ti,"Norm"); if (cmpii(sqri(t), int2n(n + 2)) > 0) t = subii(t, int2n(N)); return gerepileuptoint(ltop, t); }
/* return a bound for T_2(P), P | polbase in C[X] * NB: Mignotte bound: A | S ==> * |a_i| <= binom(d-1, i-1) || S ||_2 + binom(d-1, i) lc(S) * * Apply to sigma(S) for all embeddings sigma, then take the L_2 norm over * sigma, then take the sup over i. **/ static GEN nf_Mignotte_bound(GEN nf, GEN polbase) { GEN G = gmael(nf,5,2), lS = leading_term(polbase); /* t_INT */ GEN p1, C, N2, matGS, binlS, bin; long prec, i, j, d = degpol(polbase), n = degpol(nf[1]), r1 = nf_get_r1(nf); binlS = bin = vecbinome(d-1); if (!gcmp1(lS)) binlS = gmul(lS, bin); N2 = cgetg(n+1, t_VEC); prec = gprecision(G); for (;;) { nffp_t F; matGS = cgetg(d+2, t_MAT); for (j=0; j<=d; j++) gel(matGS,j+1) = arch_for_T2(G, gel(polbase,j+2)); matGS = shallowtrans(matGS); for (j=1; j <= r1; j++) /* N2[j] = || sigma_j(S) ||_2 */ { gel(N2,j) = gsqrt( QuickNormL2(gel(matGS,j), DEFAULTPREC), DEFAULTPREC ); if (lg(N2[j]) < DEFAULTPREC) goto PRECPB; } for ( ; j <= n; j+=2) { GEN q1 = QuickNormL2(gel(matGS,j ), DEFAULTPREC); GEN q2 = QuickNormL2(gel(matGS,j+1), DEFAULTPREC); p1 = gmul2n(mpadd(q1, q2), -1); gel(N2,j) = gel(N2,j+1) = gsqrt( p1, DEFAULTPREC ); if (lg(N2[j]) < DEFAULTPREC) goto PRECPB; } if (j > n) break; /* done */ PRECPB: prec = (prec<<1)-2; remake_GM(nf, &F, prec); G = F.G; if (DEBUGLEVEL>1) pari_warn(warnprec, "nf_factor_bound", prec); } /* Take sup over 0 <= i <= d of * sum_sigma | binom(d-1, i-1) ||sigma(S)||_2 + binom(d-1,i) lc(S) |^2 */ /* i = 0: n lc(S)^2 */ C = mulsi(n, sqri(lS)); /* i = d: sum_sigma ||sigma(S)||_2^2 */ p1 = gnorml2(N2); if (gcmp(C, p1) < 0) C = p1; for (i = 1; i < d; i++) { GEN s = gen_0; for (j = 1; j <= n; j++) { p1 = mpadd( mpmul(gel(bin,i), gel(N2,j)), gel(binlS,i+1) ); s = mpadd(s, gsqr(p1)); } if (gcmp(C, s) < 0) C = s; } return C; }
/* pol^2 mod (polcyclo(5),N) */ static GEN sqrmod5(GEN pol, Red *R) { GEN c2,b,c,d,A,B,C,D; long lv = lg(pol); if (lv==2) return pol; if (lv==3) return sqrconst(pol, R); c = gel(pol,3); c2 = shifti(c,1); d = gel(pol,2); if (lv==4) { A = sqri(d); B = mulii(c2, d); C = sqri(c); A = centermodii(A, R->N, R->N2); B = centermodii(B, R->N, R->N2); C = centermodii(C, R->N, R->N2); return mkpoln(3,A,B,C); } b = gel(pol,4); if (lv==5) { A = mulii(b, subii(c2,b)); B = addii(sqri(c), mulii(b, subii(shifti(d,1),b))); C = subii(mulii(c2,d), sqri(b)); D = mulii(subii(d,b), addii(d,b)); } else { /* lv == 6 */ GEN a = gel(pol,5), a2 = shifti(a,1); /* 2a(d - c) + b(2c - b) */ A = addii(mulii(a2, subii(d,c)), mulii(b, subii(c2,b))); /* c(c - 2a) + b(2d - b) */ B = addii(mulii(c, subii(c,a2)), mulii(b, subii(shifti(d,1),b))); /* (a-b)(a+b) + 2c(d - a) */ C = addii(mulii(subii(a,b),addii(a,b)), mulii(c2,subii(d,a))); /* 2a(b - c) + (d-b)(d+b) */ D = addii(mulii(a2, subii(b,c)), mulii(subii(d,b), addii(d,b))); } A = centermodii(A, R->N, R->N2); B = centermodii(B, R->N, R->N2); C = centermodii(C, R->N, R->N2); D = centermodii(D, R->N, R->N2); return mkpoln(4,A,B,C,D); }
static void subfields_poldata(GEN T, poldata *PD) { GEN nf,L,dis; T = shallowcopy(get_nfpol(T, &nf)); PD->pol = T; setvarn(T, 0); if (nf) { PD->den = Q_denom(gel(nf,7)); PD->roo = gel(nf,6); PD->dis = mulii(absi(gel(nf,3)), sqri(gel(nf,4))); } else { PD->den = initgaloisborne(T,NULL,ZX_get_prec(T), &L,NULL,&dis); PD->roo = L; PD->dis = absi(dis); } }
/* return a bound for T_2(P), P | polbase * max |b_i|^2 <= 3^{3/2 + d} / (4 \pi d) [P]_2, * where [P]_2 is Bombieri's 2-norm * Sum over conjugates */ static GEN nf_Beauzamy_bound(GEN nf, GEN polbase) { GEN lt,C,run,s, G = gmael(nf,5,2), POL, bin; long i,prec,precnf, d = degpol(polbase), n = degpol(nf[1]); precnf = gprecision(G); prec = MEDDEFAULTPREC; bin = vecbinome(d); POL = polbase + 2; /* compute [POL]_2 */ for (;;) { run= real_1(prec); s = real_0(prec); for (i=0; i<=d; i++) { GEN p1 = gnorml2(arch_for_T2(G, gmul(run, gel(POL,i)))); /* T2(POL[i]) */ if (!signe(p1)) continue; if (lg(p1) == 3) break; /* s += T2(POL[i]) / binomial(d,i) */ s = addrr(s, gdiv(p1, gel(bin,i+1))); } if (i > d) break; prec = (prec<<1)-2; if (prec > precnf) { nffp_t F; remake_GM(nf, &F, prec); G = F.G; if (DEBUGLEVEL>1) pari_warn(warnprec, "nf_factor_bound", prec); } } lt = leading_term(polbase); s = gmul(s, mulis(sqri(lt), n)); C = powrshalf(stor(3,DEFAULTPREC), 3 + 2*d); /* 3^{3/2 + d} */ return gdiv(gmul(C, s), gmulsg(d, mppi(DEFAULTPREC))); }
void tileMap::pickRowDelta(bool showProgress,Fl_Progress *progress,int alg,int order){ if(currentProject->pal->rowCntPal<=1){ fl_alert("This function needs more than one palette row to work"); return; } if(alg<0){ alg=menuPopupArray(deltaAlgLbl,deltaAlgTooltip,0,deltaChoices); if(alg<0) return; } pushTilemapAll(true); pushTilesAll(tTypeTile); if(order<0){ order=menuPopupArray(deltaAlgLbl,deltaAlgTooltip,0,deltaOrderChoices); if(order<0) return; } if(order>0){ pushPaletteAll(); sortBy(order>3?order-4:order-1,order<4); } unsigned type_temp=palTypeGen; uint8_t tempSet=0; double d[4];//Delta uint32_t di[4];//Delta integer uint32_t x; uint8_t t; uint8_t temp[256];//Just as a word of caution this is used for both sprintf temporary buffer and temporary truecolor tile buffer uint32_t w,h; w=mapSizeW*8; h=mapSizeHA*8; uint8_t * imagein=(uint8_t*)malloc(w*h*4); truecolor_to_image(imagein,-1); uint8_t **imageout=(uint8_t**)malloc(currentProject->pal->rowCntPal*sizeof(void*)); uint32_t xtile=0,ytile=0; if(showProgress){ progress->maximum(currentProject->pal->rowCntPal*3); progress->value(0); } for(x=0;x<currentProject->pal->rowCntPal;++x){//This function has too many hard coded values The four should be a variable with the amount of palette rows if(showProgress){ snprintf((char*)temp,256,"Dithering %d",x); progress->label((char*)temp); Fl::check(); } imageout[x]=(uint8_t*)malloc(w*h*4); truecolor_to_image(imageout[x],-1); if(showProgress){ progress->value((x*3)+1); Fl::check(); } ditherImage(imageout[x],w,h,true,true,true,x); if(showProgress){ progress->value((x*3)+2); Fl::check(); } ditherImage(imageout[x],w,h,true,false,true,x); if(showProgress){ progress->value((x*3)+3); Fl::check(); } } if(showProgress){ progress->maximum(mapSizeHA); progress->label("Picking tiles based on delta"); } unsigned per; if((currentProject->gameSystem==NES)&&(currentProject->subSystem&NES2x2)) per=2; else per=1; for (uint_fast32_t a=0;a<(h*w*4)-(w*4*per);a+=w*4*8*per){//a tiles y for (uint_fast32_t b=0;b<w*4;b+=32*per){//b tiles x if(alg==2||alg==1) memset(di,0,currentProject->pal->rowCntPal*sizeof(uint32_t)); else{ std::fill(d,d+currentProject->pal->rowCntPal,0.); } if ((type_temp != 0) && (currentProject->gameSystem == segaGenesis)){ tempSet=(currentProject->tms->maps[currentProject->curPlane].get_prio(xtile,ytile)^1)*8; set_palette_type_force(tempSet); } for(t=0;t<currentProject->pal->rowCntPal;++t){ for(unsigned c=0;c<per*w*4*8;c+=w*4*8){ for(uint32_t y=0;y<w*4*8;y+=w*4){//pixels y for(unsigned e=0;e<per*32;e+=32){ if(imagein[a+b+y+x+3+c+e]!=0){//Avoid checking transparency switch(alg){ case 0: for(x=0;x<32;x+=4) d[t]+=std::abs(ciede2000rgb(imagein[a+b+y+x+c+e],imagein[a+b+y+x+1+c+e],imagein[a+b+y+x+2+c+e],imageout[t][a+b+y+x+c+e],imageout[t][a+b+y+x+1+c+e],imageout[t][a+b+y+x+2+c+e])); break; case 1: for(x=0;x<32;x+=4) di[t]+=ColourDistance(imagein[a+b+y+x+c+e],imagein[a+b+y+x+1+c+e],imagein[a+b+y+x+2+c+e],imageout[t][a+b+y+x+c+e],imageout[t][a+b+y+x+1+c+e],imageout[t][a+b+y+x+2+c+e]); break; case 3: case 4: case 5: for(x=0;x<32;x+=4){ double h[2],l[2],s[2]; rgbToHsl255(imagein[a+b+y+x+c+e],imagein[a+b+y+x+1+c+e],imagein[a+b+y+x+2+c+e],h,s,l); rgbToHsl255(imageout[t][a+b+y+x+c+e],imageout[t][a+b+y+x+1+c+e],imageout[t][a+b+y+x+2+c+e],h+1,s+1,l+1); d[t]+=std::abs(pickIt(h[0],s[0],l[0],alg-3)-pickIt(h[1],s[1],l[1],alg-3)); } break; default://Usually case 2 for(x=0;x<32;x+=4) di[t]+=sqri(imagein[a+b+y+x+c+e]-imageout[t][a+b+y+x+c+e])+sqri(imagein[a+b+y+x+1+c+e]-imageout[t][a+b+y+x+1+c+e])+sqri(imagein[a+b+y+x+2+c+e]-imageout[t][a+b+y+x+2+c+e]); } } } } } } unsigned sillyrow; if(alg==2||alg==1) sillyrow=pick4Delta(di,currentProject->pal->rowCntPal); else sillyrow=pick4Delta(d,currentProject->pal->rowCntPal); set_pal_row(xtile,ytile,sillyrow); for(unsigned c=0,i=0;c<per*w*4*8;c+=w*4*8,++i){ for(unsigned e=0,j=0;e<per*32;e+=32,++j){ uint_fast32_t truecolor_tile_ptr=0; for (uint_fast32_t y=0;y<w*4*8;y+=w*4){//pixels y memcpy(&temp[truecolor_tile_ptr],&imageout[sillyrow][a+b+y+c+e],32); truecolor_tile_ptr+=32; } currentProject->tileC->truecolor_to_tile_ptr(sillyrow,get_tile(xtile+j,ytile+i),temp,false,false); } } xtile+=per; } if(showProgress){ if((a%(w*4*8*16))==0){ progress->value(ytile); if(window){ window->redraw(); Fl::check(); } } } xtile=0; ytile+=per; } free(imagein); for(unsigned i=0;i<currentProject->pal->rowCntPal;++i) free(imageout[i]); free(imageout); if(currentProject->gameSystem == segaGenesis) set_palette_type(); }
int G3AccumVertColor (int nVertex, CFloatVector3 *pColorSum, CVertColorData *vcdP, int nThread) { int i, j, nLights, nType, bSkipHeadlight = gameOpts->ogl.bHeadlight && !gameStates.render.nState, bTransform = gameStates.render.nState && !gameStates.ogl.bUseTransform, nSaturation = gameOpts->render.color.nSaturation; int nBrightness, nMaxBrightness = 0; float fLightDist, fAttenuation, fLightAngle, spotEffect, NdotL, RdotE; CFloatVector3 spotDir, lightDir, lightPos, vertPos, vReflect; CFloatVector3 lightColor, colorSum, vertColor = CFloatVector3::Create (0.0f, 0.0f, 0.0f); CDynLight* prl; CDynLightIndex* sliP = &lightManager.Index (0) [nThread]; CActiveDynLight* activeLightsP = lightManager.Active (nThread) + sliP->nFirst; CVertColorData vcd = *vcdP; #if DBG if (nThread == 0) nThread = nThread; if (nThread == 1) nThread = nThread; #endif colorSum = *pColorSum; vertPos = *vcd.vertPosP - *transformation.m_info.posf [1].XYZ (); vertPos.Neg (); CFloatVector3::Normalize (vertPos); nLights = sliP->nActive; if (nLights > lightManager.LightCount (0)) nLights = lightManager.LightCount (0); i = sliP->nLast - sliP->nFirst + 1; #if DBG if ((nDbgVertex >= 0) && (nVertex == nDbgVertex)) nDbgVertex = nDbgVertex; #endif for (j = 0; (i > 0) && (nLights > 0); activeLightsP++, i--) { #if 1 if (!(prl = activeLightsP->pl)) #else if (!(prl = GetActiveRenderLight (activeLightsP, nThread))) #endif continue; nLights--; #if DBG if ((nDbgSeg >= 0) && (prl->info.nSegment == nDbgSeg) && ((nDbgSide < 0) || (prl->info.nSide == nDbgSide))) nDbgSeg = nDbgSeg; # if 0 else continue; # endif #endif if (!prl->render.bState) continue; #if 0 if (i == vcd.nMatLight) continue; #endif nType = prl->render.nType; if (bSkipHeadlight && (nType == 3)) continue; #if ONLY_HEADLIGHT if (nType != 3) continue; #endif if (prl->info.bVariable && gameData.render.vertColor.bDarkness) continue; lightColor = *(reinterpret_cast<CFloatVector3*> (&prl->info.color)); spotDir = *prl->info.vDirf.XYZ (); lightPos = *prl->render.vPosf [bTransform].XYZ (); lightDir = lightPos - *vcd.vertPosP; if (IsLightVert (nVertex, prl)) { fLightDist = 0.0f; NdotL = 1.0f; } else { fLightDist = lightDir.Mag () * gameStates.ogl.fLightRange; if (lightDir.IsZero ()) lightDir = vcd.vertNorm; else CFloatVector3::Normalize (lightDir); if ((fLightDist <= 0.1f) || vcd.vertNorm.IsZero ()) NdotL = 1.0f; else { NdotL = CFloatVector3::Dot (vcd.vertNorm, lightDir); if ((NdotL < 0.0f) && (NdotL > -0.01f)) NdotL = 0.0f; } } #if USE_FACE_DIST if (/*(nVertex < 0) &&*/ (nType < 2)) { bool bInRad = DistToFace (lightPos, *vcd.vertPosP, prl->info.nSegment, ubyte (prl->info.nSide)) == 0; CFloatVector3 dir = lightPos - *vcd.vertPosP; fLightDist = dir.Mag () * gameStates.ogl.fLightRange; CFloatVector3::Normalize (dir); float dot = CFloatVector3::Dot (vcd.vertNorm, dir); if (NdotL <= dot) { NdotL = dot; lightDir = dir; } if (fabs (fLightDist) < 1.0f) fLightDist = 0.0f; } #endif if ((gameStates.render.nState || (nType < 2)) && (fLightDist > 0.0f)) { // decrease the distance between light and vertex by the light's radius // check whether the vertex is behind the light or the light shines at the vertice's back // if any of these conditions apply, decrease the light radius, chosing the smaller negative angle fLightAngle = (fLightDist > 0.1f) ? -CFloatVector3::Dot (lightDir, spotDir) + 0.01f : 1.0f; #if !USE_FACE_DIST float lightRad = (fLightAngle < 0.0f) ? 0.0f : prl->info.fRad * (1.0f - 0.9f * float (sqrt (fabs (fLightAngle)))); // make rad smaller the greater the angle fLightDist -= lightRad * gameStates.ogl.fLightRange; //make light darker if face behind light source #endif } else fLightAngle = 1.0f; if (fLightDist <= 0.0f) { NdotL = 1.0f; fLightDist = 0.0f; fAttenuation = 1.0f / prl->info.fBrightness; } else { //make it decay faster float decay = min (fLightAngle, NdotL); if (decay < 0.0f) { #if 0 fLightDist -= 1e2f * decay; #else decay += 1.0000001f; fLightDist /= decay * decay; #endif } //if ((nType < 2) && (nVertex < 0)) //fLightDist *= 0.9f; #if USE_FACE_DIST if (/*(nVertex < 0) &&*/ (nType < 2)) fAttenuation = (1.0f + GEO_LIN_ATT * fLightDist + GEO_QUAD_ATT * fLightDist * fLightDist); else #endif fAttenuation = (1.0f + GEO_LIN_ATT * fLightDist + GEO_QUAD_ATT * fLightDist * fLightDist); #if USE_FACE_DIST if ((nType < 2) && (prl->info.fRad > 0.0f)) #else if ((nVertex > -1) && (prl->info.fRad > 0.0f)) #endif NdotL += (1.0f - NdotL) / (0.5f + fAttenuation / 2.0f); fAttenuation /= prl->info.fBrightness; } if (prl->info.bSpot) { if (NdotL <= 0.0f) continue; CFloatVector3::Normalize (spotDir); lightDir = -lightDir; /* lightDir [Y] = -lightDir [Y]; lightDir [Z] = -lightDir [Z]; */ //spotEffect = G3_DOTF (spotDir, lightDir); spotEffect = CFloatVector3::Dot (spotDir, lightDir); if (spotEffect <= prl->info.fSpotAngle) continue; if (prl->info.fSpotExponent) spotEffect = (float) pow (spotEffect, prl->info.fSpotExponent); fAttenuation /= spotEffect * gameStates.ogl.fLightRange; vertColor = *gameData.render.vertColor.matAmbient.XYZ () + (*gameData.render.vertColor.matDiffuse.XYZ () * NdotL); } else { vertColor = *gameData.render.vertColor.matAmbient.XYZ (); if (NdotL > 0.1f) vertColor += (*gameData.render.vertColor.matDiffuse.XYZ () * NdotL); else if (NdotL >= 0.0f) vertColor += (*gameData.render.vertColor.matDiffuse.XYZ () * 0.1f); else NdotL = 0.0f; } vertColor *= lightColor; if ((NdotL > 0.0f) && (fLightDist > 0.0f) && (vcd.fMatShininess > 0.0f) /* && vcd.bMatSpecular */) { //RdotV = max (dot (Reflect (-Normalize (lightDir), Normal), Normalize (-vertPos)), 0.0); if (!prl->info.bSpot) //need direction from light to vertex now lightDir.Neg (); vReflect = CFloatVector3::Reflect (lightDir, vcd.vertNorm); CFloatVector3::Normalize (vReflect); #if DBG if ((nDbgVertex >= 0) && (nVertex == nDbgVertex)) nDbgVertex = nDbgVertex; #endif RdotE = CFloatVector3::Dot (vReflect, vertPos); if (RdotE > 0.0f) { //spec = pow (Reflect dot lightToEye, matShininess) * matSpecular * lightSpecular vertColor += (lightColor * (float) pow (RdotE, vcd.fMatShininess)); } } if ((nSaturation < 2) || gameStates.render.bHaveLightmaps) {//sum up color components colorSum = colorSum + vertColor * (1.0f / fAttenuation); } else { //use max. color components vertColor = vertColor * fAttenuation; nBrightness = sqri ((int) (vertColor [R] * 1000)) + sqri ((int) (vertColor [G] * 1000)) + sqri ((int) (vertColor [B] * 1000)); if (nMaxBrightness < nBrightness) { nMaxBrightness = nBrightness; colorSum = vertColor; } else if (nMaxBrightness == nBrightness) { if (colorSum [R] < vertColor [R]) colorSum [R] = vertColor [R]; if (colorSum [G] < vertColor [G]) colorSum [G] = vertColor [G]; if (colorSum [B] < vertColor [B]) colorSum [B] = vertColor [B]; } } j++; } if (j) { if ((nSaturation == 1) || gameStates.render.bHaveLightmaps) { //if a color component is > 1, cap color components using highest component value float cMax = colorSum [R]; if (cMax < colorSum [G]) cMax = colorSum [G]; if (cMax < colorSum [B]) cMax = colorSum [B]; if (cMax > 1) { colorSum [R] /= cMax; colorSum [G] /= cMax; colorSum [B] /= cMax; } } *pColorSum = colorSum; } #if DBG if (nLights) nLights = 0; #endif if (!RENDERPATH) lightManager.ResetNearestToVertex (nVertex, nThread); return j; }