Permalink
Cannot retrieve contributors at this time
Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign up
Fetching contributors…
| unit Calc; | |
| interface | |
| uses Windows, TypeDefinitions, Math3D, FormulaClass; | |
| function CalcMandT(Header: TPMandHeader10; PLightVals: TPLightVals; PCTS: TPCalcThreadStats; | |
| PsiLight5: TPsiLight5; hSLoffset, FSIstart, FSIoffset: Integer; hRect: TRect): Boolean; | |
| function CalcDEfull(It3Dex: TPIteration3Dext; mctp: Pointer{PMCTparameter}): Double; | |
| function CalcDEanalytic(It3Dex: TPIteration3Dext; mctp: Pointer{PMCTparameter}): Double; | |
| //function CalcDE4point(It3Dex: TPIteration3Dext; mctp: Pointer): Double; | |
| procedure CalcHS(PMCT: PMCTparameter; hsPsiLight: TPsiLight5; y: Integer); | |
| procedure IniIt3D(PMCT: PMCTparameter; It3Dex: TPIteration3Dext); | |
| //procedure RegulationUpdate(const ActDE, LastDE, LastStep: Double; var DEmul: Single); | |
| procedure CalcZposAndRough(siLight: TPsiLight5; mct: PMCTparameter; const ZZ: Double); | |
| procedure DelayCalcPart(ThreadCount: Integer; PCTS: TPCalcThreadStats); | |
| //procedure FreeCalcMaps; | |
| procedure IniCalcMaps({MCTparas: PMCTparameter;} Header: TPMandHeader10); | |
| procedure CopyFormulas(const OldFormulas: array of TCustomFormula; | |
| MCTparas: PMCTparameter; var CFormulas: array of TFormulaClass); | |
| procedure RayMarch(RMrec: TPRaymarchRec); | |
| function SplineIpolMap(x, y: Double; PCalcMap: TPLightMap): TVec3D; | |
| procedure RMdoBinSearch(pMCTparas: PMCTparameter; var DE, RLastStepWidth{, LastDE}: Double); | |
| procedure RMCalculateVgradsFOV(pMCTparas: PMCTparameter; ix: Integer); | |
| procedure RMmaxLengthToCutPlane(pMCTparas: PMCTparameter; var dLength: Double; var itmp: Integer; vPos: TPPos3D); | |
| procedure RMdoColorOnIt(pMCTparas: PMCTparameter); | |
| procedure RMdoColor(pMCTparas: PMCTparameter); | |
| procedure RMcalcNanglesForCut(pMCTparas: PMCTparameter; CutPlane: Integer); | |
| procedure RMdoBinSearchIt(pMCTparas: PMCTparameter; var ZZ: Double); | |
| procedure RMdoSecantSearch(pMCTparas: PMCTparameter; var DE, RLastStepWidth, RLastDE: Double); | |
| procedure RMCalculateNormals(pMCTparas: PMCTparameter; var NN: Single); | |
| procedure RMCalculateNormalsOnSmoothIt(pMCTparas: PMCTparameter; var NN: Single); | |
| procedure RMCalculateStartPos(pMCTparas: PMCTparameter; ix, iy: Integer); | |
| procedure RMCalcRoughness(N: TPVec3D; var sRough: Single; dt2, dsG: PDouble); | |
| function CalcDEnoADE(It3Dex: TPIteration3Dext; mctp: Pointer): Double; | |
| function RMcalcVLight(StepCount: Single): Integer; | |
| //function CalcDEfullNoCol(It3Dex: TPIteration3Dext; mctp: Pointer): Double; | |
| var CalcMaps: array[0..2] of TLightMap; //max 3 lightmaps? todo: Global Map Handler with depencies + exclusive free+load | |
| MapIsMissing: LongBool; | |
| // CalcDE: TCaldDEfunction = CalcDEfull; | |
| implementation | |
| uses Mand, LightAdjust, CalcThread, CalcThread2D, HeaderTrafos, Math, Maps, | |
| Navigator, SysUtils, Types, DivUtils, Forms, ImageProcess, FileHandling, | |
| MapSequences; | |
| //{$CODEALIGN 8} | |
| {procedure FreeCalcMaps; | |
| begin | |
| if Mand3DForm.Button2.Caption <> 'Stop' then | |
| begin | |
| FreeLightMap(CalcMaps[0]); | |
| FreeLightMap(CalcMaps[1]); | |
| FreeLightMap(CalcMaps[2]); | |
| end; | |
| end; } | |
| function RMcalcVLight(StepCount: Single): Integer; | |
| asm | |
| push ecx | |
| fld dword [ebp + 8] | |
| fistp dword [esp] | |
| mov eax, [esp] | |
| cmp eax, 16383 | |
| jle @1 | |
| mov eax, 16383 | |
| @1: bsr ecx, eax | |
| jz @2 | |
| sub ecx, 6 | |
| jle @2 | |
| shr eax, cl | |
| shl ecx, 7 | |
| or eax, ecx | |
| @2: pop ecx | |
| end; | |
| {var i, i2: Integer; //ebp+8 | |
| begin | |
| if StepCount > 16383 then i := 16383 else i := Round(StepCount); | |
| i2 := 0; | |
| while i > 127 do | |
| begin | |
| i := i shr 1; | |
| Inc(i2); | |
| end; | |
| Result := i or (i2 shl 7); | |
| end; } | |
| procedure IniCalcMaps(Header: TPMandHeader10); //todo: scan Formulas for 'MAP' + integer and get value from varpointer | |
| var i, i2, j, n, c, Mcount: Integer; | |
| bIsIpol: LongBool; | |
| MA: array[0..2] of Integer; | |
| begin | |
| Mcount := 0; | |
| bIsIpol := (PTHeaderCustomAddon(Header.PCFAddon).bOptions1 and 3) = 1; | |
| if bIsIpol then i2 := 2 else i2 := 5; | |
| for i := 0 to i2 do if bIsIpol or (PTHeaderCustomAddon(Header.PCFAddon).Formulas[i].iItCount <> 0) then | |
| for j := 0 to Min(16, PTHeaderCustomAddon(Header.PCFAddon).Formulas[i].iOptionCount) - 1 do | |
| begin | |
| if PTCustomFormula(Header.PHCustomF[i]).byOptionTypes[j] = 2 then //RangeCheck | |
| if Pos('MAP', UpperCase(PTCustomFormula(Header.PHCustomF[i]).sOptionStrings[j])) > 0 then | |
| begin | |
| n := Round(MinMaxCS(0, PTHeaderCustomAddon(Header.PCFAddon).Formulas[i].dOptionValue[j], 33000)); | |
| if (n > 0) and (n < 32001) and (Mcount < 3) then | |
| begin | |
| for c := 0 to Mcount - 1 do if MA[c] = n then n := 0; //already in list | |
| if n > 0 then begin | |
| MA[Mcount] := n; | |
| Inc(Mcount); | |
| end; | |
| end; | |
| end; | |
| end; | |
| for i := 0 to 2 do | |
| begin | |
| j := 0; | |
| c := 0; | |
| while j < Mcount do // delete already loaded maps from list | |
| begin | |
| if (CalcMaps[i].LMnumber = MA[j]) and | |
| ((TMapSequenceListProvider.GetInstance.GetSequence(MA[j]) = nil) or | |
| (CalcMaps[i].LMframe = TMapSequenceFrameNumberHolder.GetCurrFrameNumber)) then begin | |
| Dec(Mcount); | |
| for n := j to Mcount - 1 do MA[n] := MA[n + 1]; | |
| Inc(c); | |
| end; | |
| Inc(j); | |
| end; | |
| if c = 0 then FreeLightMap(@CalcMaps[i]); | |
| end; | |
| for i := 0 to Mcount - 1 do | |
| begin | |
| for j := 0 to 2 do if CalcMaps[j].LMnumber = 0 then | |
| begin | |
| LoadLightMapNr(MA[i], @CalcMaps[j]); | |
| Break; | |
| end; | |
| end; | |
| { FreeLightMap(CalcMaps[0]); //no, mark maps as notused, afterwards free only ehich are still notused! | |
| FreeLightMap(CalcMaps[1]); | |
| FreeLightMap(CalcMaps[2]); } | |
| end; | |
| procedure CopyFormulas(const OldFormulas: array of TCustomFormula; | |
| MCTparas: PMCTparameter; var CFormulas: array of TFormulaClass); | |
| var i: Integer; | |
| begin | |
| for i := 0 to 5 do | |
| begin | |
| CFormulas[i] := TFormulaClass.Create; | |
| CFormulas[i].AssignOld(@OldFormulas[i]); | |
| MCTparas.fHPVar[i] := CFormulas[i].pConstPointer16; | |
| MCTparas.fHybrid[i] := ThybridIteration2(CFormulas[i].pCodePointer); | |
| end; | |
| end; | |
| function CalcMandT(Header: TPMandHeader10; PLightVals: TPLightVals; PCTS: TPCalcThreadStats; | |
| PsiLight5: TPsiLight5; hSLoffset, FSIstart, FSIoffset: Integer; hRect: TRect): Boolean; | |
| var x, ThreadCount: Integer; | |
| MCTparas: TMCTparameter; | |
| MandCalcThread: array of TMandCalcThread; | |
| MandCalcThread2D: array of T2DcalcThread; | |
| OldVerbose: Boolean; | |
| begin | |
| ThreadCount := Min(Mand3DForm.UpDown3.Position, Header.Height); | |
| try | |
| MCTparas := getMCTparasFromHeader(Header^, True); | |
| Result := MCTparas.bMCTisValid; | |
| if Result then begin | |
| MCTparas.pSiLight := PsiLight5; | |
| MCTparas.SLoffset := hSLoffset; | |
| MCTparas.FSIstart := FSIstart; | |
| MCTparas.FSIoffset := FSIoffset; | |
| MCTparas.PLVals := PLightVals; | |
| MCTparas.PCalcThreadStats := PCTS; | |
| MCTparas.CalcRect := hRect; | |
| if MCTparas.calc3D then SetLength(MandCalcThread, ThreadCount) | |
| else SetLength(MandCalcThread2D, ThreadCount); | |
| end; | |
| // for x := 0 to 511 do DEreduce1[x] := 1; | |
| // for x := 0 to 511 do DEreduce2[x] := 1; | |
| { for x := 0 to 16383 do begin | |
| DEColStat[x] := 0; | |
| DEColStatCount[x] := 0; | |
| end; | |
| // for x := 0 to 255 do RoughStat[x] := 0; //histo test } | |
| except | |
| Mand3DForm.OutMessage('There was an error, please report bug and send the current parameters!'); | |
| Result := False; | |
| end; | |
| if Result then | |
| begin | |
| PCTS.ctCalcRect := hRect; | |
| for x := 1 to ThreadCount do | |
| begin | |
| PCTS.CTrecords[x].iActualYpos := -1; | |
| PCTS.CTrecords[x].iActualXpos := 0; | |
| PCTS.CTrecords[x].i64DEsteps := 0; | |
| PCTS.CTrecords[x].iDEAvrCount := 0; | |
| PCTS.CTrecords[x].i64Its := 0; | |
| PCTS.CTrecords[x].iItAvrCount := 0; | |
| PCTS.CTrecords[x].MaxIts := 0; | |
| MCTparas.iThreadId := x; | |
| if MCTparas.calc3D then | |
| begin | |
| try | |
| MandCalcThread[x - 1] := TMandCalcThread.Create(True); | |
| MandCalcThread[x - 1].FreeOnTerminate := True; | |
| {$ifdef PARAMS_PER_THREAD} | |
| OldVerbose := bGetMCTPverbose; | |
| try | |
| bGetMCTPverbose := False; | |
| MCTparas := getMCTparasFromHeader(Header^, True); | |
| MCTparas.pSiLight := PsiLight5; | |
| MCTparas.SLoffset := hSLoffset; | |
| MCTparas.FSIstart := FSIstart; | |
| MCTparas.FSIoffset := FSIoffset; | |
| MCTparas.PLVals := PLightVals; | |
| MCTparas.PCalcThreadStats := PCTS; | |
| MCTparas.CalcRect := hRect; | |
| finally | |
| bGetMCTPverbose := OldVerbose; | |
| end; | |
| {$endif PARAMS_PER_THREAD} | |
| MandCalcThread[x - 1].MCTparas := MCTparas; | |
| MandCalcThread[x - 1].Priority := cTPrio[Mand3DForm.ComboBox2.ItemIndex]; | |
| PCTS.CTrecords[x].isActive := 1; | |
| PCTS.CThandles[x] := MandCalcThread[x - 1]; | |
| // CopyFormulas(calcHybridCustoms, @MandCalcThread[x - 1].MCTparas, MandCalcThread[x - 1].Formulas); | |
| except | |
| ThreadCount := x - 1; | |
| Break; | |
| end; | |
| end else begin | |
| try | |
| MandCalcThread2D[x - 1] := T2DcalcThread.Create(True); | |
| MandCalcThread2D[x - 1].FreeOnTerminate := True; | |
| {$ifdef PARAMS_PER_THREAD} | |
| OldVerbose := bGetMCTPverbose; | |
| try | |
| bGetMCTPverbose := False; | |
| MCTparas := getMCTparasFromHeader(Header^, True); | |
| MCTparas.pSiLight := PsiLight5; | |
| MCTparas.SLoffset := hSLoffset; | |
| MCTparas.FSIstart := FSIstart; | |
| MCTparas.FSIoffset := FSIoffset; | |
| MCTparas.PLVals := PLightVals; | |
| MCTparas.PCalcThreadStats := PCTS; | |
| MCTparas.CalcRect := hRect; | |
| finally | |
| bGetMCTPverbose := OldVerbose; | |
| end; | |
| {$endif PARAMS_PER_THREAD} | |
| MandCalcThread2D[x - 1].MCTparas := MCTparas; | |
| MandCalcThread2D[x - 1].Priority := cTPrio[Mand3DForm.ComboBox2.ItemIndex]; | |
| PCTS.CTrecords[x].isActive := 1; | |
| PCTS.CThandles[x] := MandCalcThread2D[x - 1]; | |
| except | |
| ThreadCount := x - 1; | |
| Break; | |
| end; | |
| end; | |
| end; | |
| PCTS.HandleType := 1; | |
| if MCTparas.calc3D then | |
| begin | |
| for x := 0 to ThreadCount - 1 do MandCalcThread[x].MCTparas.iThreadCount := ThreadCount; | |
| end else begin | |
| for x := 0 to ThreadCount - 1 do MandCalcThread2D[x].MCTparas.iThreadCount := ThreadCount; | |
| end; | |
| PCTS.iTotalThreadCount := ThreadCount; | |
| PCTS.cCalcTime := GetTickCount; | |
| Header.bHScalculated := 0; | |
| if MCTparas.calc3D then | |
| begin | |
| for x := 0 to ThreadCount - 1 do MandCalcThread[x].Start; | |
| end else | |
| for x := 0 to ThreadCount - 1 do MandCalcThread2D[x].Start; | |
| end; | |
| end; | |
| {function CR(de, R: Double): Double; | |
| var rR: Double; | |
| begin | |
| rR := Min0MaxCD(de/R, 1); | |
| Result := 2*rR*rR*rR - 3*rR*rR + 1; | |
| end; } | |
| function CalcDEanalytic(It3Dex: TPIteration3Dext; mctp: Pointer): Double; | |
| begin | |
| with PMCTparameter(mctp)^ do | |
| begin | |
| if It3Dex.DEoption = 20 then //dIFS | |
| begin | |
| It3Dex.Rold := msDEstop * sStepWm103; //for heightmap formulas speedup, absolute DEstop | |
| It3Dex.RStopD := It3Dex.Rold; //if already closer then stop iterating... | |
| It3Dex.bIsInsideRender := bInsideRendering; | |
| end; | |
| Result := mMandFunctionDE(@It3Dex.C1) * dDEscale; | |
| MaxItsResult := It3Dex.MaxIt; | |
| if It3Dex.DEoption = 20 then Inc(MaxItsResult) else | |
| if Result < msDEstop * s025 then Result := msDEstop * s025; //MaxCDvar(var ds, ddest: Double); | |
| DEoptionResult := It3Dex.DEoption; | |
| if bCalcInside then | |
| begin | |
| if DEoptionResult = 20 then //DEoptionResult.. in DEcomb the one who rules the raystep (for faster insides in decomb) | |
| Result := msDEstop * 2 - Result | |
| else | |
| begin | |
| Result := msDEstop * 4 - Result * 3; | |
| if Result >= msDEstop then Dec(It3Dex.ItResultI); | |
| end; | |
| end; | |
| end; | |
| end; | |
| {function CalcDEanalytic(It3Dex: TPIteration3Dext; mctp: Pointer): Double; | |
| asm //eax edx | |
| push esi //ecx can be changed in functions! | |
| push ebx //the whale2 testpars were bad | |
| lea esi, eax + 136 | |
| lea ebx, edx + 180 | |
| cmp dword [esi + TIteration3Dext.DEoption - 136], 20 //TMCTparameter | |
| jnz @1 | |
| fld dword [ebx + TMCTparameter.msDEstop - 180] | |
| fmul dword [ebx + TMCTparameter.sStepWm103 - 180] | |
| fst qword [esi + TIteration3Dext.Rold - 136] | |
| fstp qword [esi + TIteration3Dext.RStopD - 136] | |
| mov eax, [ebx + TMCTparameter.bInsideRendering - 180] | |
| mov [esi + TIteration3Dext.bIsInsideRender - 136], eax | |
| @1: lea eax, esi + TIteration3Dext.C1 - 136 | |
| call dword [ebx + TMCTparameter.mMandFunctionDE - 180] | |
| fmul dword [ebx + TMCTparameter.dDEscale - 180] | |
| mov eax, [esi + TIteration3Dext.MaxIt - 136] | |
| mov [ebx + TMCTparameter.MaxItsResult - 180], eax | |
| cmp dword [esi + TIteration3Dext.DEoption - 136], 20 | |
| jnz @2 | |
| inc dword [ebx + TMCTparameter.MaxItsResult - 180] | |
| jmp @4 | |
| @2: fld dword [ebx + TMCTparameter.msDEstop - 180] | |
| fmul s025 //msDEstop*0.25, Result | |
| fcom | |
| fwait | |
| fnstsw ax | |
| shr ah, 1 | |
| jc @3 | |
| fxch | |
| @3: fstp st //result | |
| @4: mov eax, [esi + TIteration3Dext.DEoption - 136] | |
| mov [ebx + TMCTparameter.DEoptionResult - 180], eax | |
| cmp dword [ebx + TMCTparameter.bCalcInside - 180], 0 | |
| jz @5 | |
| fld dword [ebx + TMCTparameter.msDEstop - 180] | |
| fadd st, st | |
| cmp eax, 20 | |
| jnz @6 | |
| fsubrp //result:=msDEstop*2-result | |
| jmp @5 | |
| @6: fadd st, st | |
| fxch //result, msDEstop*4 | |
| fmul s3 | |
| fsubp //result:=msDEstop*4-result*3 | |
| fcom dword [ebx + TMCTparameter.msDEstop - 180] | |
| fstsw ax | |
| sahf | |
| jb @5 | |
| dec dword [esi + TIteration3Dext.ItResultI - 136] | |
| @5: pop ebx | |
| pop esi | |
| end; } | |
| procedure RestoreF1DEcomb(DEcombRec: TPBufDEcomb; mctp: PMCTparameter); | |
| begin // restore first hybrid vals | |
| with mctp^ do | |
| begin | |
| pIt3Dext.MaxIt := iMaxIt; | |
| pIt3Dext.DEoption := DEoption; | |
| PInteger(@pIt3Dext.iRepeatFrom)^ := PInteger(@RepeatFrom1)^; | |
| pIt3Dext.EndTo := wEndTo; | |
| bCalcInside := bInsideRendering; | |
| IsCustomDE := IsCustomDE1; | |
| dDEscale := DEcombRec.bufMCTdDEscale; | |
| mMandFunction := DEcombRec.bufMCTMandFunction; | |
| mMandFunctionDE := DEcombRec.bufMCTMandFunctionDE; | |
| end; | |
| end; | |
| procedure PrepareF1DEcomb(DEcombRec: TPBufDEcomb; mctp: PMCTparameter); | |
| begin //load second hybrid part | |
| with mctp^ do | |
| begin | |
| PInteger(@pIt3Dext.iRepeatFrom)^ := PInteger(@RepeatFrom2)^; | |
| pIt3Dext.EndTo := iEnd2; | |
| DEcombRec.bufMCTMandFunction := mMandFunction; | |
| DEcombRec.bufMCTMandFunctionDE := mMandFunctionDE; | |
| mMandFunction := mMandFunction2; | |
| mMandFunctionDE := mMandFunctionDE2; | |
| DEcombRec.bufIt3DItResultI := pIt3Dext.ItResultI; | |
| DEcombRec.bufIt3DOtrap := pIt3Dext.Otrap; | |
| DEcombRec.bufIt3DSmoothItD := pIt3Dext.SmoothItD; | |
| DEcombRec.bufMCTdDEscale := dDEscale; | |
| DEcombRec.bufMCTmaxItsResult := MaxItsResult; | |
| dDEscale := dDEscale2; | |
| IsCustomDE := IsCustomDE2; | |
| bCalcInside := False; | |
| pIt3Dext.MaxIt := iMaxitF2; | |
| pIt3Dext.DEoption := DEoption2; | |
| end; | |
| end; | |
| {procedure Prepare3Dgrad(DEcombRec: TPBufDEcomb; It3Dex: TPIteration3Dext); | |
| begin | |
| DEcombRec.bufMCTCalcSIT := It3Dex.CalcSIT; | |
| DEcombRec.bufIt3DItResultI := It3Dex.MaxIt; | |
| DEcombRec.bufIt3DOtrap := It3Dex.Rout; | |
| DEcombRec.bufIt3DSmoothItD := It3Dex.SmoothItD; | |
| It3Dex.CalcSIT := False; | |
| It3Dex.MaxIt := It3Dex.ItResultI; | |
| It3Dex.RStop := Sqr(It3Dex.RStop) * 64; | |
| mCopyVec(@DEcombRec.bufVec3D, @It3Dex.C1); | |
| end; | |
| procedure Restore3Dgrad(DEcombRec: TPBufDEcomb; It3Dex: TPIteration3Dext); | |
| begin | |
| It3Dex.ItResultI := It3Dex.MaxIt; //new, restore ItResult | |
| It3Dex.Rout := DEcombRec.bufIt3DOtrap; | |
| It3Dex.MaxIt := DEcombRec.bufIt3DItResultI; | |
| It3Dex.SmoothItD := DEcombRec.bufIt3DSmoothItD; | |
| It3Dex.CalcSIT := DEcombRec.bufMCTCalcSIT; | |
| mCopyVec(@It3Dex.C1, @DEcombRec.bufVec3D); | |
| end; } | |
| { | |
| procedure NotVar(var b: LongBool); | |
| asm | |
| cmp dword [eax], 0 | |
| je @@1 | |
| mov dword [eax], 0 | |
| ret | |
| @@1: | |
| mov dword [eax], -1 | |
| end; } | |
| function CalcDEnoADE(It3Dex: TPIteration3Dext; mctp: Pointer): Double; | |
| var bufMCTCalcSIT, bufMaxIt: Integer; | |
| // bufIt3DSmoothItD: Single; | |
| bufD, bufRout, Rst, wt, dt: Double; | |
| begin | |
| with PMCTparameter(mctp)^ do | |
| begin | |
| mMandFunction(@It3Dex.C1); | |
| if bInsideRendering and (It3Dex.ItResultI = It3Dex.MaxIt) then Result := 0 else | |
| begin | |
| if It3Dex.Rout < d1em200 then Result := 0 else | |
| begin | |
| { Prepare3Dgrad(@DEcombRec, It3Dex); | |
| mAddVecWeight(@It3Dex.C1, @Vgrads[2], mctDEoffset); | |
| mMandFunction(@It3Dex.C1); | |
| dt := Sqr(DEcombRec.bufIt3DOtrap - It3Dex.Rout); | |
| mCopyAddVecWeight(@It3Dex.C1, @DEcombRec.bufVec3D, @Vgrads[1], mctDEoffset); | |
| mMandFunction(@It3Dex.C1); | |
| wt := Sqr(DEcombRec.bufIt3DOtrap - It3Dex.Rout); | |
| mCopyAddVecWeight(@It3Dex.C1, @DEcombRec.bufVec3D, @Vgrads[0], mctDEoffset); | |
| mMandFunction(@It3Dex.C1); | |
| Rst := Sqr(DEcombRec.bufIt3DOtrap - It3Dex.Rout); } | |
| // bufIt3DSmoothItD := It3Dex.SmoothItD; | |
| bufMCTCalcSIT := PInteger(@It3Dex.CalcSIT)^; //bytebool | |
| bufMaxIt := It3Dex.MaxIt; | |
| bufRout := It3Dex.Rout; | |
| bufD := It3Dex.C1; | |
| It3Dex.CalcSIT := False; | |
| It3Dex.MaxIt := It3Dex.ItResultI; | |
| It3Dex.RStop := Rstop3D; | |
| It3Dex.C1 := It3Dex.C1 + mctDEoffset; | |
| mMandFunction(@It3Dex.C1); | |
| dt := Sqr(bufRout - It3Dex.Rout); | |
| It3Dex.C1 := bufD; | |
| bufD := It3Dex.C2; | |
| It3Dex.C2 := It3Dex.C2 + mctDEoffset; | |
| mMandFunction(@It3Dex.C1); | |
| wt := Sqr(bufRout - It3Dex.Rout); | |
| It3Dex.C2 := bufD; | |
| bufD := It3Dex.C3; | |
| It3Dex.C3 := It3Dex.C3 + mctDEoffset; | |
| mMandFunction(@It3Dex.C1); | |
| Rst := Sqr(bufRout - It3Dex.Rout); | |
| It3Dex.C3 := bufD; | |
| { v := AddVecF(AddVecF(ScaleVector(TPVec3D(@Vgrads[0])^, Rst), | |
| ScaleVector(TPVec3D(@Vgrads[1])^, wt)), | |
| ScaleVector(TPVec3D(@Vgrads[2])^, dt)); | |
| dd := DotOfVectorsNormalize(@v, @mVGradsFOV); } | |
| { if Rst > wt then | |
| begin | |
| if Rst > dt then dd := DotOfVectorsNormalize(@Vgrads[0], @mVGradsFOV) | |
| else dd := DotOfVectorsNormalize(@Vgrads[2], @mVGradsFOV); | |
| end | |
| else if wt > dt then | |
| dd := DotOfVectorsNormalize(@Vgrads[1], @mVGradsFOV) | |
| else dd := DotOfVectorsNormalize(@Vgrads[2], @mVGradsFOV); | |
| sZstepDiv2 := sZstepDiv + (1 - sZstepDiv) * (0.5 - Abs(dd) * 0.5);} | |
| Result := bufRout * Ln(bufRout) * dDEscale / (Sqrt(Rst + wt + dt) + mctDEoffset006); | |
| It3Dex.Rout := bufRout; | |
| It3Dex.ItResultI := It3Dex.MaxIt; | |
| It3Dex.MaxIt := bufMaxIt; | |
| // It3Dex.SmoothItD := bufIt3DSmoothItD; | |
| PInteger(@It3Dex.CalcSIT)^ := bufMCTCalcSIT; | |
| It3Dex.RStop := dRStop; | |
| // mCopyVec(@It3Dex.C1, @DEcombRec.bufVec3D); | |
| end; | |
| end; | |
| MaxItsResult := It3Dex.MaxIt; | |
| if Result < msDEstop * 0.25 then Result := msDEstop * 0.25; //MaxCDvar(DS025, Rst); | |
| DEoptionResult := It3Dex.DEoption; | |
| if bCalcInside then | |
| begin | |
| Result := msDEstop * 4 - Result * 3; | |
| if (Result >= msDEstop) then Dec(It3Dex.ItResultI); | |
| end; | |
| end; | |
| end; | |
| function CalcDEfull(It3Dex: TPIteration3Dext; mctp: Pointer{PMCTparameter}): Double; | |
| var DEcombRec: TBufDEcomb; | |
| DS025, RD1, Rst, wt, dt: Double; | |
| label go1; | |
| begin | |
| with PMCTparameter(mctp)^ do | |
| begin | |
| DS025 := msDEstop * 0.25; | |
| if IsCustomDE then | |
| begin | |
| if It3Dex.DEoption = 20 then //dIFS | |
| begin | |
| It3Dex.Rold := msDEstop * sStepWm103; //for heightmap formulas speedup, absolute DEstop | |
| It3Dex.bIsInsideRender := bInsideRendering; | |
| It3Dex.RStopD := msDEstop * sStepWm103; | |
| end; | |
| Result := mMandFunctionDE(@It3Dex.C1) * dDEscale; | |
| wt := Abs(It3Dex.w); | |
| dt := Abs(It3Dex.Deriv1); | |
| end | |
| else | |
| begin //3d gradient | |
| mMandFunction(@It3Dex.C1); | |
| if bInsideRendering and (It3Dex.ItResultI = It3Dex.MaxIt) then Result := 0 else | |
| begin | |
| if It3Dex.Rout < d1em200 then Result := 0 else | |
| begin | |
| DEcombRec.bufMCTCalcSIT := PLongBool(@It3Dex.CalcSIT)^; //bytebool | |
| DEcombRec.bufIt3DItResultI := It3Dex.MaxIt; | |
| DEcombRec.bufIt3DOtrap := It3Dex.Rout; | |
| DEcombRec.bufVec3D[0] := It3Dex.C1; | |
| It3Dex.CalcSIT := False; | |
| It3Dex.MaxIt := It3Dex.ItResultI; | |
| It3Dex.RStop := Rstop3D; | |
| It3Dex.C1 := It3Dex.C1 + mctDEoffset; | |
| mMandFunction(@It3Dex.C1); | |
| dt := Sqr(DEcombRec.bufIt3DOtrap - It3Dex.Rout); | |
| It3Dex.C1 := DEcombRec.bufVec3D[0]; | |
| DEcombRec.bufVec3D[0] := It3Dex.C2; | |
| It3Dex.C2 := It3Dex.C2 + mctDEoffset; | |
| mMandFunction(@It3Dex.C1); | |
| wt := Sqr(DEcombRec.bufIt3DOtrap - It3Dex.Rout); | |
| It3Dex.C2 := DEcombRec.bufVec3D[0]; | |
| DEcombRec.bufVec3D[0] := It3Dex.C3; | |
| It3Dex.C3 := It3Dex.C3 + mctDEoffset; | |
| mMandFunction(@It3Dex.C1); | |
| Rst := Sqr(DEcombRec.bufIt3DOtrap - It3Dex.Rout); | |
| It3Dex.C3 := DEcombRec.bufVec3D[0]; | |
| Result := DEcombRec.bufIt3DOtrap * Ln(DEcombRec.bufIt3DOtrap) * dDEscale / | |
| (Sqrt(Rst + wt + dt) + mctDEoffset006); | |
| It3Dex.Rout := DEcombRec.bufIt3DOtrap; | |
| It3Dex.ItResultI := It3Dex.MaxIt; | |
| It3Dex.MaxIt := DEcombRec.bufIt3DItResultI; | |
| PLongBool(@It3Dex.CalcSIT)^ := DEcombRec.bufMCTCalcSIT; | |
| It3Dex.RStop := dRStop; | |
| // It3Dex.SmoothItD := DEcombRec.bufIt3DSmoothItD; | |
| { Prepare3Dgrad(@DEcombRec, It3Dex); | |
| // try //test | |
| mAddVecWeight(@It3Dex.C1, @Vgrads[2], mctDEoffset); | |
| mMandFunction(@It3Dex.C1); | |
| dt := Sqr(DEcombRec.bufIt3DOtrap - It3Dex.Rout); | |
| mCopyAddVecWeight(@It3Dex.C1, @DEcombRec.bufVec3D, @Vgrads[1], mctDEoffset); | |
| mMandFunction(@It3Dex.C1); | |
| wt := Sqr(DEcombRec.bufIt3DOtrap - It3Dex.Rout); | |
| mCopyAddVecWeight(@It3Dex.C1, @DEcombRec.bufVec3D, @Vgrads[0], mctDEoffset); | |
| mMandFunction(@It3Dex.C1); | |
| Rst := Sqr(DEcombRec.bufIt3DOtrap - It3Dex.Rout); | |
| Result := DEcombRec.bufIt3DOtrap * Ln(DEcombRec.bufIt3DOtrap) * dDEscale / //div0 in ln if Rout=0 | |
| (Sqrt(Rst + wt + dt) + (mctDEoffset * s006)); | |
| // except end; | |
| It3Dex.Rout := DEcombRec.bufIt3DOtrap; | |
| It3Dex.ItResultI := It3Dex.MaxIt; | |
| It3Dex.MaxIt := DEcombRec.bufIt3DItResultI; | |
| It3Dex.SmoothItD := DEcombRec.bufIt3DSmoothItD; | |
| It3Dex.CalcSIT := DEcombRec.bufMCTCalcSIT; | |
| It3Dex.RStop := dRStop; | |
| mCopyVec(@It3Dex.C1, @DEcombRec.bufVec3D); } | |
| end; | |
| end; | |
| end; | |
| MaxItsResult := iMaxIt; | |
| if It3Dex.DEoption = 20 then Inc(MaxItsResult) else MaxCDvar(DS025, Result); | |
| DEoptionResult := It3Dex.DEoption; | |
| if FormulaType > 0 then //DEcomb type 1:min 2:max 3:maxInv 4:miS1 5:miS2 6: mix f1 first 7: mix f2-6 first | |
| begin | |
| PrepareF1DEcomb(@DEcombRec, mctp); //bCalcInside disabled here, is done at end for whole hybrid (bInsideRendering still set for dIFS) | |
| // try//test | |
| if FormulaType = 3 then bCalcInside := not bCalcInside;//NotVar(bCalcInside); | |
| if IsCustomDE then Rst := CalcDEanalytic(It3Dex, mctp) | |
| else Rst := CalcDEnoADE(It3Dex, mctp); | |
| case FormulaType of | |
| 1: if Rst >= Result then goto go1 else Result := Rst; //minDE comb | |
| 2..3: if Rst > Result then Result := Rst else //..3: MaxInv: Invert the DE of one formula and combine "max" to cut off parts | |
| begin | |
| go1: It3Dex.ItResultI := DEcombRec.bufIt3DItResultI; | |
| It3Dex.SmoothItD := DEcombRec.bufIt3DSmoothItD; | |
| It3Dex.Otrap := DEcombRec.bufIt3DOtrap; | |
| MaxItsResult := DEcombRec.bufMCTmaxItsResult; | |
| DEoptionResult := DEoption; | |
| end; | |
| 4..5: begin | |
| if Rst >= Result then //< PMCTparameter(mctp).MaxItsResult := PMCTparameter(mctp).iMaxitF2 else | |
| begin | |
| It3Dex.ItResultI := DEcombRec.bufIt3DItResultI; | |
| MaxItsResult := DEcombRec.bufMCTmaxItsResult; | |
| DEoptionResult := DEoption; | |
| end; | |
| if FormulaType = 4 then //linear | |
| Result := MinCD(Rst - Clamp0D(sDEcombSmooth - Result), | |
| Result - Clamp0D(sDEcombSmooth - Rst)) | |
| else | |
| begin //smooth | |
| RD1 := Clamp0D(sDEcombSmooth - Result - msDEstop); | |
| dt := Clamp0D(sDEcombSmooth - Rst - msDEstop); | |
| Result := MinCD(Rst - RD1 * (sDEcombSmooth - dt) / sDEcombSmooth, | |
| Result - dt * (sDEcombSmooth - RD1) / sDEcombSmooth); | |
| end; | |
| Rst := Abs(Rst); | |
| wt := Abs(Result); | |
| dt := 1 / (wt + Rst + s1em10); | |
| It3Dex.SmoothItD := (It3Dex.SmoothItD * wt + DEcombRec.bufIt3DSmoothItD * Rst) * dt; | |
| It3Dex.Otrap := (It3Dex.Otrap * wt + DEcombRec.bufIt3DOtrap * Rst) * dt; | |
| end; | |
| else | |
| begin //6..7 dIFS mix: first common fractal until bailout or maxits, then dIFS for distance.. 6: Mix, first f1..fendh1 | |
| case DEmixCol of //only in calcDEcol function, not on every step (no calcsit etc)!? | |
| 0: begin | |
| It3Dex.SmoothItD := It3Dex.SmoothItD + DEcombRec.bufIt3DSmoothItD; | |
| It3Dex.Otrap := (It3Dex.Otrap + DEcombRec.bufIt3DOtrap) * 0.5; | |
| end; | |
| 1: begin | |
| It3Dex.SmoothItD := DEcombRec.bufIt3DSmoothItD; | |
| It3Dex.Otrap := DEcombRec.bufIt3DOtrap; | |
| end; | |
| //2: color of second formula, is already | |
| end; | |
| case DEoption of | |
| 5, 6: Result := Rst / dt; //It3Dex.Deriv1; | |
| 2,11: Result := Rst / wt; //It3Dex.w; | |
| else | |
| begin | |
| Result := Rst * Power(Abs(FmixPow), -1 - DEcombRec.bufIt3DItResultI); // other method with additional value | |
| end; | |
| end; | |
| end; | |
| end; | |
| // finally //test | |
| RestoreF1DEcomb(@DEcombRec, mctp); | |
| { pIt3Dext.MaxIt := iMaxIt; | |
| pIt3Dext.DEoption := DEoption; | |
| PInteger(@pIt3Dext.iRepeatFrom)^ := PInteger(@RepeatFrom1)^; | |
| pIt3Dext.EndTo := wEndTo; | |
| bCalcInside := bInsideRendering; | |
| IsCustomDE := IsCustomDE1; | |
| dDEscale := DEcombRec.bufMCTdDEscale; | |
| mMandFunction := DEcombRec.bufMCTMandFunction; | |
| mMandFunctionDE := DEcombRec.bufMCTMandFunctionDE; } | |
| // end; | |
| end; | |
| if bCalcInside then | |
| begin | |
| if DEoptionResult = 20 then Result := msDEstop * 2 - Result else | |
| begin | |
| Result := msDEstop * 4 - Result * 3; | |
| if (Result >= msDEstop) then Dec(It3Dex.ItResultI); //else probs with decomb and rpow3-> no stop... | |
| end; //after bin search this can produce noise because of both sides possible? | |
| end; | |
| end; | |
| end; | |
| //dsG negative? | |
| procedure RMCalcRoughness(N: TPVec3D; var sRough: Single; dt2, dsG: PDouble); | |
| {begin // eax edx ecx [ebp+8] | |
| // dT2 := Noffset * 0.5 / (dM * StepSNorm); | |
| sRough := Clamp01D(Sqrt(d1em100 + dSG^ * 7 * Sqr(dt2^) / //was: fp overflow vals about 1e-100 ? | |
| (d1em100 + Sqr(N[0]) + Sqr(N[1]) + Sqr(N[2]))) - 0.05); //} | |
| asm | |
| cmp SupportSSE2, 0 | |
| jz @@1 | |
| movupd xmm0, [eax] | |
| movsd xmm1, [eax + 16] | |
| movsd xmm2, [ecx] | |
| mulpd xmm0, xmm0 | |
| mulsd xmm1, xmm1 | |
| mulsd xmm2, xmm2 | |
| addsd xmm1, xmm0 | |
| mov eax, [ebp + 8] | |
| unpckhpd xmm0, xmm0 | |
| mulsd xmm2, [eax] | |
| addsd xmm1, xmm0 | |
| mulsd xmm2, d7 | |
| addsd xmm1, d1em40 | |
| addsd xmm2, d1em40 | |
| xorpd xmm3, xmm3 | |
| divsd xmm2, xmm1 | |
| maxsd xmm2, xmm3 | |
| sqrtsd xmm2, xmm2 | |
| subsd xmm2, d005 | |
| maxsd xmm2, xmm3 | |
| minsd xmm2, d1p0 | |
| cvtsd2ss xmm4, xmm2 | |
| movss [edx], xmm4 | |
| jmp @end | |
| @@1: | |
| fld qword [eax] | |
| fmul st, st | |
| fld qword [eax + 8] | |
| fmul st, st | |
| faddp | |
| fld qword [eax + 16] | |
| fmul st, st | |
| faddp | |
| fadd d1em100 | |
| mov eax, [ebp + 8] | |
| fld qword [ecx] | |
| fmul st, st | |
| fmul qword [eax] | |
| fmul s7 | |
| fadd d1em100 | |
| fdivrp | |
| ftst | |
| fnstsw ax | |
| shr ah, 1 | |
| jnc @1 | |
| fstp st | |
| fldz | |
| @1: fsqrt | |
| fld s005 //0.05, sR' | |
| fcom st(1) | |
| fnstsw ax | |
| shr ah, 1 | |
| jc @up | |
| fcompp | |
| xor eax, eax | |
| mov [edx], eax | |
| jmp @end | |
| @up: | |
| fsubp | |
| fld1 | |
| fcomp st(1) | |
| fnstsw ax | |
| and ah, 41H | |
| jz @up2 | |
| fstp st | |
| fld1 | |
| @up2: | |
| fstp dword [edx] | |
| @end: | |
| end; | |
| procedure RMCalculateNormals(pMCTparas: PMCTparameter; var NN: Single); | |
| var itmp, iy, ix, SmoothN: Integer; | |
| // bIR: LongBool; | |
| Noffset, NN2, NN1, dNN, dT2, dM, dS, dSG, StepSNorm: Double; | |
| N, Vx, Vy, CT1: TVec3D; | |
| sd: TLightSD; | |
| begin | |
| with pMCTparas^ do | |
| begin | |
| // bIR := bInsideRendering; | |
| { if bInsideRendering then | |
| begin | |
| // bCalcInside := True; | |
| bInsideRendering := False; //to calc 4point DE also if ItResult=Maxit, does not help | |
| // msDEstop := msDEstop * 2; //to avoid decreasing ItResultI, does not help | |
| // end; } | |
| // if not IsCustomDE then Inc(pIt3Dext.maxIt, 4); //test | |
| pIt3Dext.CalcSIT := True; | |
| Noffset := MinCS(1, DEstop) * (1 + mZZ * mctDEstopFactor) * 0.15; | |
| mCopyVec(@CT1, @pIt3Dext.C1); | |
| dNN := CalcDE(pIt3Dext, pMCTparas); | |
| NN := pIt3Dext.SmoothItD; //for coloring | |
| pIt3Dext.CalcSIT := False; | |
| if iSmNormals = 8 then | |
| begin | |
| ClearDVec(N); | |
| StepSNorm := Noffset * 1.3333; | |
| for itmp := -2 to 2 do | |
| for iy := -2 to 2 do | |
| for ix := -2 to 2 do | |
| if (itmp or iy or ix) <> 0 then | |
| begin | |
| mCopyAddVecWeight(@pIt3Dext.C1, @CT1, @Vgrads[2], itmp * StepSNorm); | |
| mAddVecWeight(@pIt3Dext.C1, @Vgrads[1], iy * StepSNorm); | |
| mAddVecWeight(@pIt3Dext.C1, @Vgrads[0], ix * StepSNorm); | |
| dT2 := CalcDE(pIt3Dext, pMCTparas); | |
| if itmp <> 0 then N[2] := N[2] + dT2 / itmp; | |
| if iy <> 0 then N[1] := N[1] + dT2 / iy; | |
| if ix <> 0 then N[0] := N[0] + dT2 / ix; | |
| end; | |
| ScaleVectorV(@N, 0.0075); | |
| end | |
| else | |
| begin | |
| mAddVecWeight(@pIt3Dext.C1, @Vgrads[2], Noffset); | |
| N[2] := CalcDE(pIt3Dext, pMCTparas); //Zgradient | |
| mAddVecWeight(@pIt3Dext.C1, @Vgrads[2], -2 * Noffset); | |
| N[2] := (N[2] - CalcDE(pIt3Dext, pMCTparas)) * s05; | |
| mCopyAddVecWeight(@pIt3Dext.C1, @CT1, @Vgrads[0], Noffset); | |
| N[0] := CalcDE(pIt3Dext, pMCTparas); //Xgradient | |
| mAddVecWeight(@pIt3Dext.C1, @Vgrads[0], -2 * Noffset); | |
| N[0] := (N[0] - CalcDE(pIt3Dext, pMCTparas)) * s05; | |
| mCopyAddVecWeight(@pIt3Dext.C1, @CT1, @Vgrads[1], Noffset); | |
| N[1] := CalcDE(pIt3Dext, pMCTparas); //Ygradient | |
| mAddVecWeight(@pIt3Dext.C1, @Vgrads[1], -2 * Noffset); | |
| N[1] := (N[1] - CalcDE(pIt3Dext, pMCTparas)) * s05; | |
| end; | |
| if iSmNormals > 0 then //smoothed with estimation of roughness, eg deviation from mid val | |
| begin | |
| Noffset := Noffset * 2; | |
| if iSmNormals < 8 then | |
| begin | |
| mCopyAddVecWeight(@pIt3Dext.C1, @CT1, @Vgrads[0], -Noffset); //smooth mid point | |
| dNN := dNN + CalcDE(pIt3Dext, pMCTparas); | |
| mAddVecWeight(@pIt3Dext.C1, @Vgrads[0], 2 * Noffset); | |
| dNN := dNN + CalcDE(pIt3Dext, pMCTparas); | |
| mCopyAddVecWeight(@pIt3Dext.C1, @CT1, @Vgrads[1], -Noffset); | |
| dNN := dNN + CalcDE(pIt3Dext, pMCTparas); | |
| mAddVecWeight(@pIt3Dext.C1, @Vgrads[1], 2 * Noffset); | |
| dNN := (dNN + CalcDE(pIt3Dext, pMCTparas)) * 0.2; | |
| end; | |
| SmoothN := iSmNormals; | |
| StepSNorm := Noffset * 3 / (SmoothN + s05); | |
| dM := SmoothN * 2; | |
| CreateXYVecsFromNormals(@N, @Vx, @Vy); //make ortho vector x,y related to normals | |
| RotateVectorReverse(@Vx, @Vgrads); | |
| RotateVectorReverse(@Vy, @Vgrads); | |
| mCopyAddVecWeight(@pIt3Dext.C1, @CT1, @Vx, -SmoothN * StepSNorm); | |
| NN1 := 0; | |
| dS := 0; | |
| for itmp := -SmoothN to SmoothN do | |
| begin | |
| if itmp <> 0 then | |
| begin | |
| dT2 := (CalcDE(pIt3Dext, pMCTparas) - dNN) / itmp; | |
| NN1 := NN1 + dT2; | |
| dS := dS + Sqr(dT2); | |
| end; | |
| mAddVecWeight(@pIt3Dext.C1, @Vx, StepSNorm); | |
| end; | |
| dSG := dS * dM - Sqr(NN1); | |
| mCopyAddVecWeight(@pIt3Dext.C1, @CT1, @Vy, -SmoothN * StepSNorm); | |
| NN2 := 0; | |
| dS := 0; | |
| for itmp := -SmoothN to SmoothN do | |
| begin | |
| if itmp <> 0 then | |
| begin | |
| dT2 := (CalcDE(pIt3Dext, pMCTparas) - dNN) / itmp; | |
| NN2 := NN2 + dT2; | |
| dS := dS + Sqr(dT2); | |
| end; | |
| mAddVecWeight(@pIt3Dext.C1, @Vy, StepSNorm); | |
| end; | |
| dT2 := Noffset * 0.5 / (dM * StepSNorm); | |
| dSG := dSG + dS * dM - Sqr(NN2); | |
| RMCalcRoughness(@N, sRoughness, @dT2, @dSG); | |
| // sRoughness := Clamp01D(Sqrt(d1em100 + dSG * 7 * Sqr(dT2) / //was: fp overflow vals about 1e-100 ? | |
| // (d1em100 + Sqr(N[0]) + Sqr(N[1]) + Sqr(N[2]))) - 0.05); //also called sqrt invalid! neg number? | |
| if iSmNormals < 8 then | |
| begin | |
| N[0] := N[0] + NN1 * dT2; | |
| N[1] := N[1] + NN2 * dT2; | |
| end; | |
| end; | |
| mCopyVec(@pIt3Dext.C1, @CT1); | |
| MakeWNormalsFromDVec(TPLNormals(mPsiLight), @N); | |
| if PInteger(@mPsiLight.NormalX)^ = 0 then | |
| if mPsiLight.NormalZ > 0 then mPsiLight.NormalZ := 32767 | |
| else mPsiLight.NormalZ := -32767; | |
| // if not IsCustomDE then Dec(pIt3Dext.maxIt, 4); //test | |
| // msDEstop := msDEstop * 0.5; | |
| // bInsideRendering := bIR; | |
| end; | |
| end; | |
| procedure RMCalculateNormalsOnSmoothIt(pMCTparas: PMCTparameter; var NN: Single); | |
| var itmp, SmoothN, iy, ix: Integer; | |
| Noffset, NN2, NN1, StepSNorm: Double; | |
| dT2, dM, dS, dSG: Double; | |
| N, CT1, Vx, Vy : TVec3D; | |
| begin | |
| with pMCTparas^ do | |
| begin | |
| Noffset := MinCS(1, DEstop) * (1 + mZZ * mctDEstopFactor) * 0.15; | |
| pIt3Dext.CalcSIT := True; | |
| mCopyVec(@CT1, @pIt3Dext.C1); | |
| mMandFunction(@pIt3Dext.C1); | |
| NN := pIt3Dext.SmoothItD; | |
| if iSmNormals = 8 then | |
| begin | |
| ClearDVec(N); | |
| StepSNorm := Noffset * 1.3333; | |
| for itmp := -2 to 2 do | |
| for iy := -2 to 2 do | |
| for ix := -2 to 2 do | |
| if (itmp or iy or ix) <> 0 then | |
| begin | |
| mCopyAddVecWeight(@pIt3Dext.C1, @CT1, @Vgrads[2], itmp * StepSNorm); | |
| mAddVecWeight(@pIt3Dext.C1, @Vgrads[1], iy * StepSNorm); | |
| mAddVecWeight(@pIt3Dext.C1, @Vgrads[0], ix * StepSNorm); | |
| mMandFunction(@pIt3Dext.C1); | |
| dT2 := pIt3Dext.SmoothItD; | |
| if itmp <> 0 then N[2] := N[2] - dT2 / itmp; | |
| if iy <> 0 then N[1] := N[1] - dT2 / iy; | |
| if ix <> 0 then N[0] := N[0] - dT2 / ix; | |
| end; | |
| ScaleVectorV(@N, 0.0075); | |
| end | |
| else | |
| begin | |
| mAddVecWeight(@pIt3Dext.C1, @Vgrads[2], Noffset); | |
| mMandFunction(@pIt3Dext.C1); | |
| N[2] := pIt3Dext.SmoothItD; //Zgradient | |
| mAddVecWeight(@pIt3Dext.C1, @Vgrads[2], -2 * Noffset); | |
| mMandFunction(@pIt3Dext.C1); | |
| N[2] := (pIt3Dext.SmoothItD - N[2]) * s05; | |
| mCopyAddVecWeight(@pIt3Dext.C1, @CT1, @Vgrads[0], Noffset); | |
| mMandFunction(@pIt3Dext.C1); | |
| N[0] := pIt3Dext.SmoothItD; //Xgradient | |
| mAddVecWeight(@pIt3Dext.C1, @Vgrads[0], -2 * Noffset); | |
| mMandFunction(@pIt3Dext.C1); | |
| N[0] := (pIt3Dext.SmoothItD - N[0]) * s05; | |
| mCopyAddVecWeight(@pIt3Dext.C1, @CT1, @Vgrads[1], Noffset); | |
| mMandFunction(@pIt3Dext.C1); | |
| N[1] := pIt3Dext.SmoothItD; //Ygradient | |
| mAddVecWeight(@pIt3Dext.C1, @Vgrads[1], -2 * Noffset); | |
| mMandFunction(@pIt3Dext.C1); | |
| N[1] := (pIt3Dext.SmoothItD - N[1]) * s05; | |
| end; | |
| if iSmNormals > 0 then //smoothed with estimation of roughness, eg deviation from mid val | |
| begin | |
| Noffset := Noffset * 2; | |
| mCopyAddVecWeight(@pIt3Dext.C1, @CT1, @Vgrads[0], -Noffset); //smooth mid point | |
| mMandFunction(@pIt3Dext.C1); | |
| NN := NN + pIt3Dext.SmoothItD; | |
| mAddVecWeight(@pIt3Dext.C1, @Vgrads[0], 2 * Noffset); | |
| mMandFunction(@pIt3Dext.C1); | |
| NN := NN + pIt3Dext.SmoothItD; | |
| mCopyAddVecWeight(@pIt3Dext.C1, @CT1, @Vgrads[1], -Noffset); | |
| mMandFunction(@pIt3Dext.C1); | |
| NN := NN + pIt3Dext.SmoothItD; | |
| mAddVecWeight(@pIt3Dext.C1, @Vgrads[1], 2 * Noffset); | |
| mMandFunction(@pIt3Dext.C1); | |
| NN := (NN + pIt3Dext.SmoothItD) * 0.2; | |
| SmoothN := iSmNormals; | |
| StepSNorm := Noffset * 3 / (SmoothN + s05); | |
| dM := SmoothN * 2; | |
| //make ortho vector x,y related to normals | |
| CreateXYVecsFromNormals(@N, @Vx, @Vy); | |
| RotateVectorReverse(@Vx, @Vgrads); | |
| RotateVectorReverse(@Vy, @Vgrads); | |
| mCopyAddVecWeight(@pIt3Dext.C1, @CT1, @Vx, -SmoothN * StepSNorm); | |
| NN1 := 0; | |
| dS := 0; | |
| for itmp := -SmoothN to SmoothN do | |
| begin | |
| if itmp <> 0 then | |
| begin | |
| mMandFunction(@pIt3Dext.C1); | |
| dT2 := (NN - pIt3Dext.SmoothItD) / itmp; | |
| NN1 := NN1 + dT2; | |
| dS := dS + Sqr(dT2); | |
| end; | |
| mAddVecWeight(@pIt3Dext.C1, @Vx, StepSNorm); | |
| end; | |
| dSG := dS * dM - Sqr(NN1); | |
| mCopyAddVecWeight(@pIt3Dext.C1, @CT1, @Vy, -SmoothN * StepSNorm); | |
| NN2 := 0; | |
| dS := 0; | |
| for itmp := -SmoothN to SmoothN do | |
| begin | |
| if itmp <> 0 then | |
| begin | |
| mMandFunction(@pIt3Dext.C1); | |
| dT2 := (NN - pIt3Dext.SmoothItD) / itmp; //smoothit + inf! | |
| NN2 := NN2 + dT2; | |
| dS := dS + Sqr(dT2); | |
| end; | |
| mAddVecWeight(@pIt3Dext.C1, @Vy, StepSNorm); | |
| end; | |
| dT2 := Noffset * s05 / (dM * StepSNorm); | |
| dSG := dSG + dS * dM - Sqr(NN2); | |
| RMCalcRoughness(@N, sRoughness, @dT2, @dSG); | |
| // sRoughness := Clamp01D(Sqrt(d1em100 + (dSG + dS * dM - Sqr(NN2)) * 7 * Sqr(dT2) / //was: fp overflow vals about 1e-100 ? | |
| // (d1em100 + Sqr(N[0]) + Sqr(N[1]) + Sqr(N[2]))) - 0.05); | |
| if iSmNormals < 8 then | |
| begin | |
| N[0] := N[0] + NN1 * dT2; | |
| N[1] := N[1] + NN2 * dT2; | |
| end; | |
| end; | |
| mCopyVec(@pIt3Dext.C1, @CT1); | |
| if bInsideRendering then ScaleVectorV(@N, -1); | |
| MakeWNormalsFromDVec(TPLNormals(mPsiLight), @N); | |
| if PInteger(@mPsiLight.NormalX)^ = 0 then | |
| if mPsiLight.NormalZ > 0 then mPsiLight.NormalZ := 32767 | |
| else mPsiLight.NormalZ := -32767; | |
| { if PInteger(@mPsiLight.NormalX)^ = 0 then | |
| mPsiLight.NormalZ := -32767 | |
| else | |
| begin | |
| RotateVectorReverse(@N, @Vgrads); //N=-NAN,-NAN,-NAN if smoothit fails | |
| if mVGradsFOV[0] * N[0] + mVGradsFOV[1] * N[1] + mVGradsFOV[2] * N[2] > 0 then // proof if vec is behind slice, pointing in wrong direction | |
| mPsiLight.NormalZ := -mPsiLight.NormalZ; | |
| end;} | |
| end; | |
| end; | |
| procedure RMdoBinSearchIt(pMCTparas: PMCTparameter; var ZZ: Double); | |
| var dT1, dmul: Double; | |
| itmp, MItmp, MItmp2: Integer; | |
| LastSI, R, LastDif, YP{, dTmul}: Single; | |
| firstIt: LongBool; | |
| begin | |
| with TPIteration3Dext(pMCTparas.pIt3Dext)^ do | |
| begin | |
| YP := maxIt - 0.99; | |
| MItmp := pMCTparas.iMaxIt; | |
| MItmp2 := pMCTparas.iMaxItF2; | |
| if DEoption <> 20 then Inc(pMCTparas.iMaxIt); | |
| MaxIt := pMCTparas.iMaxIt; | |
| if pMCTparas.DEoption2 <> 20 then Inc(pMCTparas.iMaxItF2); | |
| itmp := pMCTparas.iDEAddSteps; | |
| CalcSIT := True; | |
| dT1 := 0; | |
| dmul := 1; | |
| firstIt := True; | |
| repeat | |
| ZZ := ZZ + dT1; | |
| mAddVecWeight(@C1, @pMCTparas.mVgradsFOV, dT1); | |
| pMCTparas.CalcDE(pMCTparas.pIt3Dext, pMCTparas); | |
| if not firstIt then | |
| begin | |
| if LastDif < Abs(YP - SmoothItD) then | |
| begin | |
| ZZ := ZZ - dT1; | |
| mAddVecWeight(@C1, @pMCTparas.mVgradsFOV, -dT1); | |
| SmoothItD := LastSI; | |
| if dT1 > 0 then dmul := dmul * s05 | |
| else dmul := dmul * 0.7; | |
| end; | |
| end; | |
| LastDif := Abs(YP - SmoothItD); | |
| LastSI := SmoothItD; | |
| if SmoothItD > maxIt - 0.1 then dT1 := -3 else | |
| begin | |
| ZZ := ZZ - 0.001; | |
| mAddVecWeight(@C1, @pMCTparas.mVgradsFOV, -0.001); | |
| pMCTparas.CalcDE(pMCTparas.pIt3Dext, pMCTparas); | |
| R := LastSI - SmoothItD; | |
| if Abs(R) < 1e-30 then | |
| dT1 := Integer(LastSI < SmoothItD) - s05 | |
| else if R < 0 then dT1 := (YP - SmoothItD) / (R * 500) | |
| else dT1 := (YP - SmoothItD) / (R * 1000); | |
| if dT1 > 4 then dT1 := Sqrt(dT1) * 2 else | |
| if dT1 < -9 then dT1 := Sqrt(-dT1) * -3; | |
| dT1 := dT1 * dmul + 0.0005; | |
| end; | |
| firstIt := False; | |
| Dec(itmp); | |
| until itmp < 0; | |
| maxIt := MItmp; | |
| pMCTparas.iMaxIt := MItmp; | |
| pMCTparas.iMaxItF2 := MItmp2; | |
| end; | |
| end; | |
| procedure RMCalculateStartPos(pMCTparas: PMCTparameter; ix, iy: Integer); | |
| //eax edx ecx | |
| {begin | |
| with pMCTparas^ do | |
| begin | |
| pIt3Dext.C1 := Ystart[0] + Vgrads[0,0] * ix + Vgrads[1,0] * iy; | |
| pIt3Dext.C2 := Ystart[1] + Vgrads[0,1] * ix + Vgrads[1,1] * iy; | |
| pIt3Dext.C3 := Ystart[2] + Vgrads[0,2] * ix + Vgrads[1,2] * iy; | |
| end; } | |
| asm | |
| add eax, $78 | |
| cmp dword [eax + TMCTparameter.MCTCameraOptic - $78], 2 | |
| jne @@2 | |
| mov ecx, dword [eax + TMCTparameter.pIt3Dext - $78] | |
| fld qword [eax + TMCTparameter.Ystart - $78] | |
| fld qword [eax + TMCTparameter.Ystart - $78 + 8] | |
| fld qword [eax + TMCTparameter.Ystart - $78 + 16] | |
| fstp qword [ecx + TIteration3Dext.C3] | |
| fstp qword [ecx + TIteration3Dext.C2] | |
| fstp qword [ecx + TIteration3Dext.C1] | |
| ret | |
| @@2: | |
| cmp SupportSSE2, 0 | |
| jz @@1 | |
| push ecx | |
| push edx | |
| cvtpi2pd xmm7, [esp] //xx,yy | |
| mov ecx, dword [eax + TMCTparameter.pIt3Dext - $78] //+68 | |
| lea edx, eax + $78 //TMCTparameter.Ystart | |
| movapd xmm6, xmm7 | |
| unpckhpd xmm7, xmm7 //yy,yy | |
| unpcklpd xmm6, xmm6 //xx,xx | |
| movupd xmm0, [eax + TMCTparameter.Vgrads - $78] | |
| movupd xmm2, [eax + TMCTparameter.Vgrads - $60] | |
| movupd xmm4, [edx + TMCTparameter.Ystart - $78 - $78] | |
| mulpd xmm0, xmm6 | |
| mulsd xmm6, [eax + TMCTparameter.Vgrads - $68] | |
| mulpd xmm2, xmm7 | |
| mulsd xmm7, [eax + TMCTparameter.Vgrads - $50] | |
| addpd xmm0, xmm2 | |
| addsd xmm6, xmm7 | |
| addpd xmm0, xmm4 | |
| addsd xmm6, [edx + TMCTparameter.Ystart - $78 - $68] | |
| movupd [ecx + TIteration3Dext.C1], xmm0 | |
| movsd [ecx + TIteration3Dext.C3], xmm6 | |
| pop edx | |
| pop ecx | |
| ret | |
| @@1: | |
| push ecx | |
| fild dword [esp] | |
| push edx | |
| fild dword [esp] //xx,yy | |
| mov ecx, dword [eax + TMCTparameter.pIt3Dext - $78] //+68 | |
| lea edx, eax + $78 //TMCTparameter.Ystart | |
| fld qword [eax + TMCTparameter.Vgrads - $78] | |
| fmul st, st(1) | |
| fld qword [eax + TMCTparameter.Vgrads - $78 + 24] | |
| fmul st, st(3) | |
| faddp | |
| fadd qword [edx + TMCTparameter.Ystart - $78 - $78] | |
| fstp qword [ecx + TIteration3Dext.C1] | |
| fld qword [eax + TMCTparameter.Vgrads - $78 + 8] | |
| fmul st, st(1) | |
| fld qword [eax + TMCTparameter.Vgrads - $78 + 32] | |
| fmul st, st(3) | |
| faddp | |
| fadd qword [edx + TMCTparameter.Ystart - $70 - $78] | |
| fstp qword [ecx + TIteration3Dext.C2] //xx,yy | |
| fmul qword [eax + TMCTparameter.Vgrads - $78 + 16] | |
| fxch | |
| fmul qword [eax + TMCTparameter.Vgrads - $78 + 40] | |
| faddp | |
| fadd qword [edx + TMCTparameter.Ystart - $68 - $78] | |
| fstp qword [ecx + TIteration3Dext.C3] | |
| pop edx | |
| pop ecx | |
| end; | |
| procedure CalculateVgradsFOVCommon(MCTparas: PMCTparameter; ix: Integer); | |
| begin | |
| MCTparas.CAFX := (MCTparas.FOVXoff - ix) * MCTparas.FOVXmul; | |
| BuildViewVectorDFOV(MCTparas.CAFY, MCTparas.CAFX, @MCTparas.mVgradsFOV); | |
| RotateVectorReverse(@MCTparas.mVgradsFOV, @MCTparas.VGrads); | |
| end; | |
| procedure CalculateVgradsFOVRect(MCTparas: PMCTparameter; ix: Integer); | |
| begin | |
| MCTparas.CAFX := (MCTparas.FOVXoff - ix) * MCTparas.FOVXmul; | |
| MCTparas.mVgradsFOV[0] := -MCTparas.CAFX; | |
| MCTparas.mVgradsFOV[1] := MCTparas.CAFY; | |
| MCTparas.mVgradsFOV[2] := MCTparas.mctPlOpticZ; | |
| NormaliseVectorVar(MCTparas.mVgradsFOV); | |
| RotateVectorReverse(@MCTparas.mVgradsFOV, @MCTparas.VGrads); | |
| end; | |
| procedure CalculateVgradsFOVPanorama(MCTparas: PMCTparameter; ix: Integer); | |
| begin | |
| MCTparas.CAFX := (MCTparas.FOVXoff - ix) * MCTparas.FOVXmul; | |
| BuildViewVectorDSphereFOV(MCTparas.CAFY, MCTparas.CAFX, @MCTparas.mVgradsFOV); | |
| RotateVectorReverse(@MCTparas.mVgradsFOV, @MCTparas.VGrads); | |
| end; | |
| //eax edx | |
| procedure RMCalculateVgradsFOV(pMCTparas: PMCTparameter; ix: Integer); | |
| {begin | |
| with MCTparas do | |
| begin | |
| CAFX := (FOVXoff - ix) * FOVXmul; | |
| if bMCTPlanarOptic = 1 then //iMCTCamOption: Integer = 0:def 1:rect 2:spherepano | |
| begin | |
| VgradsFOV[0] := -CAFX; | |
| VgradsFOV[1] := CAFY; | |
| VgradsFOV[2] := mctPlOpticZ; | |
| NormaliseVectorVar(VgradsFOV); | |
| end | |
| else if bMCTPlanarOptic = 2 then | |
| BuildViewVectorDSphereFOV(CAFY, CAFX, @VgradsFOV) | |
| else BuildViewVectorDFOV(CAFY, CAFX, @VgradsFOV); | |
| RotateVectorReverse(@VgradsFOV, @VGrads); | |
| end; } | |
| asm | |
| push ebx | |
| push esi | |
| push edx //to store ix in [esp] and fiload (esp := esp-4) | |
| lea ebx, eax + $1a0 | |
| fild dword [esp] //ix | |
| fsubr dword [ebx + TMCTparameter.FOVXoff - $1a0] | |
| fmul dword [ebx + TMCTparameter.FOVXmul - $1a0] | |
| fst qword [ebx + TMCTparameter.CAFX - $1a0] // $1a0 | |
| cmp dword [ebx + TMCTparameter.MCTCameraOptic - $1a0], 1 // $1fc | |
| je @@3 | |
| fstp st | |
| lea ecx, [ebx + TMCTparameter.mVgradsFOV - $1a0] | |
| lea edx, [ebx + TMCTparameter.CAFX - $1a0] // $1a0 | |
| lea eax, [ebx + TMCTparameter.CAFY - $1a0] // $1a8 | |
| cmp dword [ebx + TMCTparameter.MCTCameraOptic - $1a0], 0 // $1fc | |
| je @@1 | |
| call BuildViewVectorDSphereFOV | |
| jmp @@2 | |
| @@3: | |
| fchs | |
| fstp qword [ebx + TMCTparameter.mVgradsFOV - $1a0] | |
| fld qword [ebx + TMCTparameter.CAFY - $1a0] // $1a8 | |
| fstp qword [ebx + TMCTparameter.mVgradsFOV - $1a0 + 8] | |
| fld dword [ebx + TMCTparameter.mctPlOpticZ - $1a0] // $204 | |
| fstp qword [ebx + TMCTparameter.mVgradsFOV - $1a0 + 16] | |
| lea eax, [ebx + TMCTparameter.mVgradsFOV - $1a0] | |
| call NormaliseVectorVar | |
| jmp @@2 | |
| @@1: | |
| call BuildViewVectorDFOV | |
| @@2: | |
| lea edx, [ebx + TMCTparameter.VGrads - $1a0] // $80 | |
| lea eax, [ebx + TMCTparameter.mVgradsFOV - $1a0] | |
| call RotateVectorReverse | |
| pop edx //to Inc(esp, 4) | |
| pop esi | |
| pop ebx | |
| end; | |
| procedure RMdoColorOnIt(pMCTparas: PMCTparameter); | |
| var i: Integer; | |
| begin | |
| with pMCTparas^do | |
| begin | |
| if ColorOnIt = 1 then mCopyVec(@pIt3Dext.x, @pIt3Dext.C1) else | |
| begin | |
| i := pIt3Dext.maxIt; | |
| pIt3Dext.maxIt := ColorOnIt - 1; | |
| pIt3Dext.RStop := Sqr(pIt3Dext.RStop) * 64; | |
| CalcDE(pIt3Dext, pMCTparas); | |
| pIt3Dext.maxIt := i; | |
| pIt3Dext.RStop := dRStop; | |
| end; | |
| end; | |
| end; | |
| //eax | |
| procedure RMdoColor(pMCTparas: PMCTparameter); | |
| {var s, s2: Single; | |
| dv: TVec3D; | |
| begin | |
| with pMCTparas.pIt3Dext^ do | |
| begin | |
| case pMCTparas.ColorOption of | |
| 1: s := Ln(Rout / (Rold + 1)) * pMCTparas.mctColorMul; | |
| 2: s := (ArcTan2(y - C2, x - C1) + Pi) * 5200; | |
| 3: s := (ArcTan2(z - C3, x - C1) + Pi) * 5200; | |
| 4: s := (ArcTan2(z - C3, y - C2) + Pi) * 5200; | |
| 5, 6: begin | |
| s := (ArcTan2(x, y) + Pi) * 5215; //output vec | |
| dv := NormaliseVector(@x); | |
| s2 := (Pi + ArcSinSafe(dv[2]) * 2) * 5215; | |
| MinMaxClip15bit(s2, pMCTparas.mPsiLight.SIgradient); | |
| end; | |
| else s := OTrap * 4096; | |
| end; | |
| MinMaxClip15bit(s, pMCTparas.mPsiLight.OTrap); | |
| end; } | |
| const | |
| cd5200: Single = 5200; | |
| cd4096: Single = 4096; | |
| cd5215: Single = 5215; | |
| asm | |
| push ebx | |
| push edi | |
| push edx //just to get dword [esp] | |
| mov edi, [eax + TMCTparameter.mPsiLight] | |
| mov ebx, [eax + TMCTparameter.pIt3Dext] | |
| movzx edx, byte [eax + TMCTparameter.ColorOption] //coloroption | |
| cmp edx, 6 | |
| jnb @@COelse | |
| jmp dword [edx * 4 + @@jmptable] | |
| @@jmptable: | |
| dd @@COelse, @@CO1, @@CO2, @@CO3, @@CO4, @@CO5 | |
| @@CO1: | |
| fld qword [ebx + 8] //Rold | |
| fld1 | |
| faddp | |
| fdivr qword [ebx + $70] //Rout | |
| fldln2 | |
| fxch | |
| fyl2x | |
| fmul dword [eax + TMCTparameter.mctColorMul] //mctColorMul | |
| jmp @@up | |
| nop | |
| @@CO2: | |
| fld qword [ebx+$20] | |
| fsub qword [ebx+$40] | |
| jmp @1 | |
| @@CO3: | |
| fld qword [ebx+$28] | |
| fsub qword [ebx+$48] | |
| @1: fld qword [ebx+$18] | |
| fsub qword [ebx+$38] | |
| @2: fpatan | |
| fldpi | |
| faddp | |
| fmul cd5200 | |
| jmp @@up | |
| @@CO4: | |
| fld qword [ebx+$28] | |
| fsub qword [ebx+$48] | |
| fld qword [ebx+$20] | |
| fsub qword [ebx+$40] | |
| jmp @2 | |
| @@CO5: | |
| fld qword [ebx+$20] | |
| fld st | |
| fmul st, st //yy,y | |
| fld qword [ebx+$18] //x,yy,y | |
| fld st | |
| fmul st, st //xx,x,yy,y | |
| fxch st(3) //y,x,yy,xx | |
| fpatan | |
| fldpi | |
| faddp | |
| fmul cd5215 //s,yy,xx | |
| fxch st(2) //xx,yy,s | |
| faddp | |
| fadd d1em100 | |
| fld qword [ebx+$28] //z,yy+xx,s norm vec[2] for arcsin | |
| fld st | |
| fmul st, st //zz,z,yy+xx,s | |
| faddp st(2), st //z,rr,s | |
| fxch //rr,z,s | |
| fsqrt //r,z,s | |
| fdivp //z/r,s | |
| @@s2: | |
| fld1 //arcsin(x) = arctan2(x, sqrt(1-x*x)) | |
| fld st(1) | |
| fmul st(0), st(0) | |
| fsubp | |
| fsqrt | |
| fpatan | |
| fadd st, st | |
| fldpi | |
| faddp | |
| fmul cd5215 | |
| fstp dword [esp] | |
| lea edx, [edi + TsiLight5.SIgradient] | |
| mov eax, esp | |
| call MinMaxClip15bit | |
| jmp @@up | |
| @@COelse: | |
| fld qword [ebx + TIteration3Dext.OTrap] | |
| fmul cd4096 | |
| @@up: | |
| fstp dword [esp] | |
| lea edx, [edi + TsiLight5.Otrap] | |
| mov eax, esp | |
| call MinMaxClip15bit | |
| pop edx | |
| pop edi | |
| pop ebx | |
| end; | |
| {procedure RMdoBinSearch(var dTmp, RLastStepWidth, mZZ: Double; RMrec: TPRaymarchRec); | |
| var dT1: Double; | |
| itmp, itst: Integer; | |
| begin | |
| with RMrec^ do | |
| begin | |
| itst := PMCTparas.iMaxit; | |
| PMCTparas.iMaxit := PIt3Dex.ItResultI; //for dIFS necessary | |
| itmp := PMCTparas.iDEAddSteps; | |
| dT1 := RLastStepWidth * -0.5; | |
| while (itmp > 0) and (Abs(dTmp - PMCTparas.msDEstop) > 0.001) do | |
| begin | |
| mZZ := mZZ + dT1; | |
| mAddVecWeight(@PIt3Dex.C1, @MarchVec, dT1); | |
| // PMCTparas.msDEstop := StartDEstop * (1 + mZZ * PMCTparas.mctDEstopFactor); | |
| PMCTparas.msDEstop := StartDEstop * (1 + Clamp0D(ActZpos + mZZ * ZZposMul) * PMCTparas.mctDEstopFactor); | |
| dTmp := CalcDE(PIt3Dex, PMCTparas); | |
| if PIt3Dex.ItResultI >= PMCTparas.MaxItsResult then | |
| dT1 := Abs(dT1) * -1 else | |
| begin | |
| if dTmp < PMCTparas.msDEstop then dT1 := Abs(dT1) * -0.55 | |
| else dT1 := Abs(dT1) * 0.55; | |
| Dec(itmp); | |
| end; | |
| end; | |
| PMCTparas.iMaxit := itst; | |
| end; | |
| end; } | |
| procedure RMmaxLengthToCutPlane(pMCTparas: PMCTparameter; var dLength: Double; var itmp: Integer; vPos: TPPos3D); | |
| var dTmp: Double; | |
| begin | |
| dLength := 0; | |
| if pMCTparas.iCutOptions <> 0 then | |
| with pMCTparas^ do | |
| begin | |
| if ((iCutOptions and 1) <> 0) and (Abs(mVgradsFOV[0]) > 1e-20) then | |
| begin | |
| if (((iCutOptions shl 3) xor PByte(Integer(@mVgradsFOV[0]) + 7)^) and $80) = 0 then dLength := 1e20 else | |
| begin | |
| dTmp := (dCOX - vPos^[0]) / mVgradsFOV[0]; | |
| if dTmp > dLength then | |
| begin | |
| dLength := dTmp; | |
| itmp := 1; | |
| end; | |
| end; | |
| end; | |
| if ((iCutOptions and 2) <> 0) and (Abs(mVgradsFOV[1]) > 1e-20) then | |
| begin | |
| if (((iCutOptions shl 2) xor PByte(Integer(@mVgradsFOV[1]) + 7)^) and $80) = 0 then dLength := 1e20 else | |
| begin | |
| dTmp := (dCOY - vPos^[1]) / mVgradsFOV[1]; | |
| if dTmp > dLength then | |
| begin | |
| dLength := dTmp; | |
| itmp := 2; | |
| end; | |
| end; | |
| end; | |
| if ((iCutOptions and 4) <> 0) and (Abs(mVgradsFOV[2]) > 1e-20) then | |
| begin | |
| if (((iCutOptions shl 1) xor PByte(Integer(@mVgradsFOV[2]) + 7)^) and $80) = 0 then dLength := 1e20 else | |
| begin | |
| dTmp := (dCOZ - vPos^[2]) / mVgradsFOV[2]; | |
| if dTmp > dLength then | |
| begin | |
| dLength := dTmp; | |
| itmp := 3; | |
| end; | |
| end; | |
| end; | |
| end; | |
| {asm // pMCTparas: PMCTparameter; var dLength: Double; var itmp: Integer; vPos: TPPos3D) | |
| push ebx // eax edx ecx | |
| push esi | |
| push edi | |
| xor esi, esi | |
| mov [edx], esi | |
| mov [edx+4], esi | |
| lea ebx, eax+TMCTparameter.iCutOptions | |
| cmp ebx, 0 | |
| jle @@1 | |
| mov esi, eax | |
| test ebx, 1 | |
| jle @@2 | |
| fld qword [esi+TMCTparameter.mVgradsFOV] | |
| fabs | |
| fcomp s1em20 | |
| fnstsw ax | |
| shr ah, 1 | |
| jc @@2 | |
| @@2: | |
| @@1: | |
| pop edi | |
| pop esi | |
| pop ebx } | |
| end; | |
| procedure RMcalcNanglesForCut(pMCTparas: PMCTparameter; CutPlane: Integer);//; PSL: TPsiLight5); | |
| {var NN: Double; | |
| N: TVec3D; | |
| itmp: Integer; | |
| begin | |
| with pMCTparas^ do | |
| begin | |
| if CutPlane > 0 then | |
| begin | |
| NN := 8388352 - ZcMul * (Sqrt(mZZ * Zcorr + 1) - 1); | |
| if NN < 0 then itmp := 0 else itmp := Round(NN); | |
| PCardinal(@mPsiLight.RoughZposFine)^ := itmp shl 8; | |
| Dec(CutPlane); | |
| if Abs(Vgrads[2, CutPlane]) < 1e-40 then NN := -1e40 else NN := -1 / Vgrads[2, CutPlane]; //rel Normals to view | |
| N[0] := Vgrads[0, CutPlane] * NN; | |
| N[1] := Vgrads[1, CutPlane] * NN; | |
| N[2] := -1; | |
| MakeWNormalsFromDVec(TPLNormals(mPsiLight), @N); | |
| end else begin | |
| PCardinal(@mPsiLight.RoughZposFine)^ := $7FFF0000; | |
| mPsiLight.NormalX := 0; | |
| mPsiLight.NormalY := 0; | |
| mPsiLight.NormalZ := -32767; | |
| end; | |
| end; } | |
| const CS8388352: Single = 8388352; | |
| asm | |
| push ebx | |
| push esi | |
| push edi | |
| add esp, -24 | |
| mov edi, [eax+TMCTparameter.mPsiLight] //PSL | |
| mov esi, edx //cutplane | |
| lea ebx, eax + 128 //MCTparas | |
| test esi, esi //if cutplane>0 | |
| jle @@1 | |
| fld1 | |
| fld qword [ebx+TMCTparameter.mZZ-128] //+104 mZZ^,1 NN := 8388352 - ZcMul * (Sqrt(mZZ * Zcorr + 1) - 1); | |
| fmul qword [ebx+TMCTparameter.Zcorr-128] //$274 | |
| fadd st, st(1) | |
| fsqrt | |
| fsubrp | |
| fmul qword [ebx+TMCTparameter.ZcMul-128] //$26c | |
| fsubr CS8388352 //NN | |
| { ftst // if NN < 0 then iTmp := 0 else itmp := Round(NN); | |
| fnstsw ax | |
| shr ah, 1 | |
| jnc @@2 | |
| xor eax, eax | |
| fstp st | |
| jmp @@3 | |
| @@2: | |
| fistp dword [esp] | |
| mov eax, [esp] | |
| shl eax, 8 // PCardinal(@PSL.RoughZposFine)^ := iTmp shl 8; | |
| @@3: | |
| mov [edi+6], eax } | |
| fistp dword [esp] | |
| mov eax, [esp] | |
| test eax, eax | |
| jns @@3 | |
| xor eax, eax | |
| @@3: | |
| shl eax, 8 // PCardinal(@PSL.RoughZposFine)^ := iTmp shl 8; | |
| mov [edi+6], eax | |
| dec esi //VGrads: +128 | |
| fld qword [ebx+esi*8+TMCTparameter.VGrads+$30-128] // if Abs(Vgrads[2, CutPlane]) < 1e-40 | |
| fabs | |
| fcomp d1em40 | |
| fnstsw ax | |
| shr ah, 1 | |
| jnc @@4 | |
| fld dm1e40 // NN := -1e40 | |
| jmp @@5 | |
| @@4: | |
| fld1 // NN := -1 / Vgrads[2, CutPlane]; | |
| fchs | |
| fdiv qword [ebx+esi*8+TMCTparameter.VGrads+$30-128] | |
| @@5: | |
| fld qword [ebx+esi*8+TMCTparameter.VGrads-128] // N[0] := Vgrads[0, CutPlane] * NN; | |
| fmul st, st(1) | |
| fstp qword [esp] | |
| fld qword [ebx+esi*8+TMCTparameter.VGrads+$18-128] // N[1] := Vgrads[1, CutPlane] * NN; | |
| fmulp | |
| fstp qword [esp+8] | |
| fld1 | |
| fchs // N[2] := -1; | |
| fstp qword [esp+16] | |
| mov edx, esp // MakeWNormalsFromDVec(TPLNormals(PSL), @N); | |
| mov eax, edi | |
| call MakeWNormalsFromDVec | |
| jmp @@6 | |
| @@1: | |
| xor eax, eax | |
| mov [edi+6], $7fff0000 | |
| mov dword [edi], eax | |
| mov word [edi+4], $8001 | |
| @@6: | |
| add esp, 24 | |
| pop edi | |
| pop esi | |
| pop ebx //} | |
| end; | |
| //eax edx ecx ebp+8 | |
| procedure RMdoSecantSearch(pMCTparas: PMCTparameter; var DE, RLastStepWidth, RLastDE: Double); | |
| var RSFmul, LastDE: Double; | |
| itmp: Integer; | |
| begin | |
| with pMCTparas^ do | |
| begin //Secant | |
| itmp := (iDEAddSteps shr 1) + 1; | |
| while Abs(DE - msDEstop) > 0.001 do | |
| begin | |
| RLastDE := NotZero(RLastDE - DE); | |
| RSFmul := RLastStepWidth * (DE - msDEstop) / RLastDE; | |
| if DE < msDEstop then | |
| begin | |
| if (RSFmul >= 0) or (RSFmul < Abs(RLastStepWidth) * -0.94) then | |
| RLastStepWidth := Abs(RLastStepWidth) * -0.5 | |
| else RLastStepWidth := RSFmul; | |
| end else begin | |
| if (RSFmul <= 0) or (RSFmul > Abs(RLastStepWidth) * 0.94) then | |
| RLastStepWidth := Abs(RLastStepWidth) * s05 | |
| else RLastStepWidth := RSFmul; | |
| end; | |
| RLastDE := DE; | |
| mZZ := mZZ + RLastStepWidth; | |
| mAddVecWeight(@pIt3Dext.C1, @mVgradsFOV, RLastStepWidth); | |
| msDEstop := DEstop * (1 + Abs(mZZ) * mctDEstopFactor); | |
| Dec(itmp); | |
| if itmp <= 0 then Break; | |
| DE := CalcDE(pIt3Dext, pMCTparas); | |
| end; | |
| end; | |
| end; | |
| //eax edx ecx ebp+8 | |
| procedure RMdoBinSearch(pMCTparas: PMCTparameter; var DE, RLastStepWidth{, RLastDE}: Double); | |
| {var RSFmul, LastDE: Double; | |
| itmp: Integer; | |
| begin | |
| with pMCTparas^ do | |
| begin //Secant | |
| itmp := iDEAddSteps shr 1; | |
| while Abs(DE - msDEstop) > 0.001 do | |
| begin | |
| RLastDE := NotZero(RLastDE - DE); | |
| RSFmul := RLastStepWidth * (DE - msDEstop) / RLastDE; | |
| if DE < msDEstop then | |
| begin | |
| if (RSFmul >= 0) or (RSFmul < Abs(RLastStepWidth) * -0.94) then | |
| RLastStepWidth := Abs(RLastStepWidth) * -0.5 | |
| else RLastStepWidth := RSFmul; | |
| end else begin | |
| if (RSFmul <= 0) or (RSFmul > Abs(RLastStepWidth) * 0.94) then | |
| RLastStepWidth := Abs(RLastStepWidth) * s05 | |
| else RLastStepWidth := RSFmul; | |
| end; | |
| RLastDE := DE; | |
| ZZ := ZZ + RLastStepWidth; | |
| mAddVecWeight(@Iteration3Dext.C1, @VgradsFOVit, RLastStepWidth); | |
| Dec(itmp); | |
| if itmp <= 0 then Break; | |
| msDEstop := DEstop * (1 + Abs(ZZ) * mctDEstopFactor); | |
| if itmp > 0 then DE := CalcDE(@Iteration3Dext, @MCTparas); | |
| end; | |
| end; | |
| end; } | |
| {var dT1: Double; | |
| itmp, itst: Integer; | |
| begin | |
| with pMCTparas^ do | |
| begin | |
| itst := iMaxit; //if DEoption = 20 ? | |
| if FormulaType = 0 then iMaxIt := pIt3Dext.ItResultI; //for dIFS ..in inside rendering wrong result in DEcomb on 2nd alt. formula | |
| itmp := iDEAddSteps; | |
| dT1 := RLastStepWidth * -0.5; | |
| while Abs(dTmp - msDEstop) > 0.001 do | |
| begin | |
| mZZ := mZZ + dT1; | |
| mAddVecWeight(@pIt3Dext.C1, @mVgradsFOV, dT1); | |
| msDEstop := DEstop * (1 + mZZ * mctDEstopFactor); | |
| Dec(itmp); | |
| if itmp <= 0 then Break; | |
| dTmp := CalcDE(pIt3Dext, pMCTparas); | |
| if pIt3Dext.ItResultI >= MaxItsResult then | |
| dT1 := -Abs(dT1) else | |
| begin | |
| if dTmp < msDEstop then dT1 := Abs(dT1) * -0.55 | |
| else dT1 := Abs(dT1) * 0.55; | |
| end; | |
| end; | |
| iMaxIt := itst; | |
| end; | |
| end; } | |
| asm | |
| push ebx | |
| push esi | |
| push edi | |
| push ebp | |
| add esp, -8 | |
| mov edi, edx //@dTmp | |
| lea esi, eax+$38 //@MCTParas (was:qTMandCalcThread) | |
| mov ebx, [esi+TMCTparameter.pIt3Dext-$38] | |
| { mov eax, [esi+TMCTparameter.iMaxit-$38] | |
| mov [esp+8], eax | |
| mov eax, [esi+TMCTparameter.iMaxitF2-$38] | |
| mov [esp+12], eax | |
| mov eax, [ebx+TIteration3Dext.ItResultI] //+$a8 | |
| cmp dword [ebx+TIteration3Dext.DEoption], 20 | |
| jne @@0 | |
| // cmp dword [esi+TMCTparameter.FormulaType-$38],0 //+$78 | |
| // jnz @@1 | |
| mov [esi+TMCTparameter.iMaxit-$38], eax | |
| mov [ebx+TIteration3Dext.maxIt], eax | |
| @@0: | |
| cmp dword [esi+TMCTparameter.DEoption2-$38], 20 | |
| jne @@1 | |
| mov [esi+TMCTparameter.iMaxitF2-$38], eax | |
| @@1: } | |
| mov ebp, [esi+TMCTparameter.iDEAddSteps-$38] //+$40 | |
| fld qword [ecx] // RLastStepWidth | |
| fmul sm05 | |
| jmp @@2 | |
| @@4: | |
| fld qword [esi+TMCTparameter.mZZ-$38] //+$68 | |
| fadd qword [esp] | |
| fstp qword [esi+TMCTparameter.mZZ-$38] //+$68 | |
| { push dword [esp+4] | |
| push dword [esp+4] | |
| lea edx, esi+TMCTparameter.mVgradsFOV-$38 | |
| lea eax, ebx+TIteration3Dext.C1 //+$68 | |
| call mAddVecWeight } | |
| fld qword [esi+TMCTparameter.mVgradsFOV-$38] | |
| fld qword [esi+TMCTparameter.mVgradsFOV-$38 + 8] | |
| fld qword [esi+TMCTparameter.mVgradsFOV-$38 + 16] | |
| fld qword [esp] | |
| fmul st(3), st | |
| fmul st(2), st | |
| fmulp | |
| fadd qword [ebx+TIteration3Dext.C1 + 16] | |
| fstp qword [ebx+TIteration3Dext.C1 + 16] | |
| fadd qword [ebx+TIteration3Dext.C1 + 8] | |
| fstp qword [ebx+TIteration3Dext.C1 + 8] | |
| fadd qword [ebx+TIteration3Dext.C1] | |
| fstp qword [ebx+TIteration3Dext.C1] | |
| fld qword [esi+TMCTparameter.mZZ-$38] //+$68 | |
| fmul dword [esi+TMCTparameter.mctDEstopFactor-$38] //+$54 | |
| fld1 | |
| faddp | |
| fmul dword [esi+TMCTparameter.DEstop-$38] //+$60 | |
| fstp dword [esi+TMCTparameter.msDEstop-$38] //+$38 msDEstop := DEstop * (1 + mZZ * mctDEstopFactor); | |
| dec ebp | |
| test ebp, ebp | |
| jle @@3 | |
| lea edx, esi-$38 | |
| mov eax, ebx | |
| call esi+TMCTparameter.CalcDE-$38 | |
| fstp qword [edi] //dTmp | |
| { mov eax, [ebx+TIteration3Dext.ItResultI] | |
| cmp eax, [esi+TMCTparameter.MaxItsResult-$38] | |
| jl @@5 | |
| fld qword [esp] | |
| fabs | |
| fchs // dT1 := -Abs(dT1) | |
| jmp @@2 | |
| @@5: } | |
| fld qword [edi] | |
| fcomp dword [esi+TMCTparameter.msDEstop-$38] //+$38 | |
| fnstsw ax | |
| fld qword [esp] | |
| fabs | |
| fmul s055 | |
| shr ah, 1 | |
| jnc @@8 | |
| fchs | |
| @@8: | |
| // dec ebp // | |
| @@2: | |
| fstp qword [esp] | |
| // test ebp, ebp // | |
| // jle @@3 // | |
| fld qword [edi] | |
| fsub dword [esi+TMCTparameter.msDEstop-$38] //+$38 | |
| fabs | |
| fcomp s0001 | |
| fnstsw ax | |
| shr ah, 1 | |
| jnc @@4 | |
| @@3: | |
| { mov eax, [esp+8] | |
| mov [esi+TMCTparameter.iMaxit-$38], eax | |
| mov [ebx+TIteration3Dext.maxIt], eax | |
| mov eax, [esp + 12] | |
| mov [esi + TMCTparameter.iMaxitF2-$38], eax } | |
| add esp, 8 | |
| pop ebp | |
| pop edi | |
| pop esi | |
| pop ebx | |
| end; //} | |
| { TRaymarchRec = record | |
| PMCTparas: PMCTparameter; | |
| PIt3Dex: TPIteration3Dext; | |
| ActPos, MarchVec, VievVec: TVec3D; | |
| ActZpos, StartDEstop, ZZposMul, DEmulVary, DEmulConst, MaxRayLength: Double; | |
| BinSteps, seed, RMresult: Integer; //result: 0: no object 1: object on DE 2: object on Itcount 3: Outside again? | |
| StepCount, StepForward, Zstepped: Single; //on start: 0/1/2 = outside/insideConstStep/insideDIFSDE? | |
| end; } | |
| procedure RayMarch(RMrec: TPRaymarchRec); | |
| var itmp: Integer; | |
| DElimited, bFirstStep: LongBool; | |
| RSFmul: Single; | |
| RLastStepWidth, dTmp, dT1, RLastDE: Double; | |
| begin | |
| with RMrec^ do | |
| begin | |
| PIt3Dex.CalcSIT := False; | |
| itmp := 0; | |
| StepCount := 0; | |
| Zstepped := 0; | |
| ZZposMul := DotOfVectorsNormalize(@MarchVec , @VievVec); | |
| PMCTparas.msDEstop := StartDEstop; | |
| bFirstStep := PMCTparas.bMCTFirstStepRandom; | |
| mCopyVec(@ActPos, @PIt3Dex.C1); | |
| Zstepped := Zstepped + StepForward; | |
| mAddVecWeight(@PIt3Dex.C1, @MarchVec, StepForward); | |
| if PMCTparas.iCutOptions > 0 then // move to begin of cutting planes todo: check on which side, modify MaxRayLength if step towards cutplane | |
| begin | |
| RMmaxLengthToCutPlane(PMCTparas, dT1, itmp, @ActPos); | |
| if dT1 > MaxRayLength then | |
| begin | |
| RMresult := 0; | |
| Exit; | |
| end else begin | |
| Zstepped := dT1; | |
| mAddVecWeight(@PIt3Dex.C1, @MarchVec, dT1); | |
| PMCTparas.msDEstop := StartDEstop * (1 + Clamp0D(ActZpos + Zstepped * ZZposMul) * PMCTparas.mctDEstopFactor); | |
| dTmp := PMCTparas.CalcDE(PIt3Dex, PMCTparas); | |
| end; | |
| end | |
| else dTmp := PMCTparas.CalcDE(PIt3Dex, PMCTparas); | |
| if (PIt3Dex.ItResultI >= PMCTparas.MaxItsResult) or (dTmp < PMCTparas.msDEstop) then // already in the set, todo: proof if same formula (DEcomb)? | |
| begin | |
| if dTmp < PMCTparas.msDEstop then RMresult := 1 else RMresult := 2; | |
| mCopyVec(@PIt3Dex.C1, @ActPos); | |
| Exit; | |
| end | |
| else | |
| begin | |
| RSFmul := 1; | |
| RLastStepWidth := dTmp * PMCTparas.sZstepDiv; | |
| // RLastDE := dTmp + RLastStepWidth; | |
| repeat | |
| if PIt3Dex.ItResultI >= PMCTparas.MaxItsResult then //inside while stepping | |
| begin | |
| dT1 := -0.5 * RLastStepWidth; | |
| Zstepped := Zstepped + dT1; | |
| mAddVecWeight(@PIt3Dex.C1, @MarchVec, dT1); | |
| PMCTparas.msDEstop := StartDEstop * (1 + Clamp0D(ActZpos + Zstepped * ZZposMul) * PMCTparas.mctDEstopFactor); | |
| dTmp := PMCTparas.CalcDE(PIt3Dex, PMCTparas); | |
| RLastStepWidth := -dT1; | |
| end; | |
| if (PIt3Dex.ItResultI < PMCTparas.iMinIt) or | |
| ((PIt3Dex.ItResultI < PMCTparas.MaxItsResult) and (dTmp >= PMCTparas.msDEstop)) then //##### next step ###### | |
| begin | |
| RLastDE := dTmp; | |
| dTmp := dTmp * PMCTparas.sZstepDiv * RSFmul; | |
| dT1 := MaxCS(PMCTparas.msDEstop, 0.4) * PMCTparas.mctMH04ZSD; | |
| if dT1 < dTmp then | |
| begin | |
| if not bFirstStep then StepCount := StepCount + dT1 / dTmp else StepCount := StepCount + Random; | |
| dTmp := dT1; | |
| end | |
| else StepCount := StepCount + 1; | |
| if bFirstStep then {..$Q- integer overflow check} | |
| begin | |
| bFirstStep := False; | |
| seed := 214013 * seed + 2531011; | |
| dTmp := ((seed shr 16) and $7FFF) * 0.000030517578125 * dTmp; | |
| end; | |
| { if DEoption = 20 then //test for dIFS, do not overstep with high DEstop vals, on high fov you have to diff new destop | |
| begin | |
| dT1 := DEstop * (1 + (ZZ + dTmp) * mctDEstopFactor) * 0.9; | |
| dTmp := MinCD(dTmp, (RLastDE - dT1) * sZstepDiv); | |
| end; } | |
| RLastStepWidth := dTmp; | |
| Zstepped := Zstepped + dTmp; | |
| mAddVecWeight(@PIt3Dex.C1, @MarchVec, dTmp); | |
| PMCTparas.msDEstop := StartDEstop * (1 + Clamp0D(ActZpos + Zstepped * ZZposMul) * PMCTparas.mctDEstopFactor); | |
| //todo: pointcam.. actZpos := distance of actPos to CamPos! | |
| dTmp := PMCTparas.CalcDE(PIt3Dex, PMCTparas); | |
| if dTmp > RLastDE + RLastStepWidth then dTmp := RLastDE + RLastStepWidth; | |
| if RLastDE > dTmp + s1em30 then | |
| begin | |
| dT1 := RLastStepWidth / (RLastDE - dTmp); | |
| if dT1 < 1 then | |
| RSFmul := maxCS(s05, dT1) | |
| else | |
| RSFmul := 1; | |
| end | |
| else RSFmul := 1; | |
| end | |
| else // ##### set found ##### | |
| begin | |
| DElimited := PIt3Dex.ItResultI < PMCTparas.MaxItsResult; | |
| if PMCTparas.iDEAddSteps > 0 then | |
| begin | |
| if DElimited then | |
| RMdoBinSearch(PMCTparas, dTmp, RLastStepWidth{, RLastDE}) | |
| else | |
| begin | |
| RMdoBinSearchIt(PMCTparas, Zstepped); | |
| end; | |
| end; | |
| ActZpos := Clamp0D(ActZpos + Zstepped * ZZposMul); | |
| if DElimited then RMresult := 1 else RMresult := 2; | |
| mCopyVec(@PIt3Dex.C1, @ActPos); | |
| Exit; | |
| end; | |
| until (Zstepped > MaxRayLength) or PMCTparas.PCalcThreadStats.pLBcalcStop^; //or ActZpos' < 0? (frontclipping) | |
| RMresult := 0; | |
| ActZpos := Clamp0D(ActZpos + Zstepped * ZZposMul); | |
| end; | |
| end; | |
| end; | |
| procedure RayMarchVV(RMrec: TPRaymarchRec); //raymarch in viewvec, extra because a bit simpler? (or: do it in asm) | |
| var itmp: Integer; | |
| DElimited, bFirstStep: LongBool; | |
| RSFmul: Single; | |
| RLastStepWidth, dTmp, dT1, RLastDE, ZZ: Double; | |
| begin | |
| with RMrec^ do | |
| begin | |
| PIt3Dex.CalcSIT := False; | |
| itmp := 0; | |
| StepCount := 0; | |
| ZZ := 0; | |
| PMCTparas.msDEstop := StartDEstop; | |
| bFirstStep := PMCTparas.bMCTFirstStepRandom; | |
| mCopyVec(@ActPos, @PIt3Dex.C1); | |
| if PMCTparas.iCutOptions > 0 then // move to begin of cutting planes todo: check on which side, modify MaxRayLength if step towards cutplane | |
| begin | |
| RMmaxLengthToCutPlane(PMCTparas, dT1, itmp, @ActPos); | |
| if dT1 > MaxRayLength then | |
| begin | |
| RMresult := 0; | |
| Exit; | |
| end else begin | |
| ZZ := dT1; | |
| mAddVecWeight(@PIt3Dex.C1, @MarchVec, dT1); | |
| PMCTparas.msDEstop := StartDEstop * (1 + ZZ * PMCTparas.mctDEstopFactor); | |
| dTmp := PMCTparas.CalcDE(PIt3Dex, PMCTparas); | |
| end; | |
| end | |
| else dTmp := PMCTparas.CalcDE(PIt3Dex, PMCTparas); | |
| if (PIt3Dex.ItResultI >= PMCTparas.MaxItsResult) or (dTmp < PMCTparas.msDEstop) then // already in the set, todo: proof if same formula (DEcomb)? | |
| begin | |
| if dTmp < PMCTparas.msDEstop then RMresult := 1 else RMresult := 2; | |
| mCopyVec(@PIt3Dex.C1, @ActPos); | |
| Exit; | |
| end | |
| else | |
| begin | |
| RSFmul := 1; | |
| RLastStepWidth := dTmp * PMCTparas.sZstepDiv; | |
| // RLastDE := dTmp + RLastStepWidth; | |
| repeat | |
| if PIt3Dex.ItResultI >= PMCTparas.MaxItsResult then //inside while stepping | |
| begin | |
| dT1 := -0.5 * RLastStepWidth; | |
| ZZ := ZZ + dT1; | |
| mAddVecWeight(@PIt3Dex.C1, @MarchVec, dT1); | |
| PMCTparas.msDEstop := StartDEstop * (1 + ZZ * PMCTparas.mctDEstopFactor); | |
| dTmp := PMCTparas.CalcDE(PIt3Dex, PMCTparas); | |
| RLastStepWidth := - dT1; | |
| end; | |
| if (PIt3Dex.ItResultI < PMCTparas.iMinIt) or | |
| ((PIt3Dex.ItResultI < PMCTparas.MaxItsResult) and (dTmp >= PMCTparas.msDEstop)) then //##### next step ###### | |
| begin | |
| RLastDE := dTmp; | |
| dTmp := dTmp * PMCTparas.sZstepDiv * RSFmul; | |
| dT1 := MaxCS(PMCTparas.msDEstop, 0.4) * PMCTparas.mctMH04ZSD; | |
| if dT1 < dTmp then | |
| begin | |
| if not bFirstStep then StepCount := StepCount + dT1 / dTmp else StepCount := StepCount + Random; | |
| dTmp := dT1; | |
| end | |
| else StepCount := StepCount + 1; | |
| if bFirstStep then {..$Q- integer overflow check} | |
| begin | |
| bFirstStep := False; | |
| seed := 214013 * seed + 2531011; | |
| dTmp := ((seed shr 16) and $7FFF) * 0.000030517578125 * dTmp; | |
| end; | |
| { if DEoption = 20 then //test for dIFS, do not overstep with high DEstop vals, on high fov you have to diff new destop | |
| begin | |
| dT1 := DEstop * (1 + (ZZ + dTmp) * mctDEstopFactor) * 0.9; | |
| dTmp := MinCD(dTmp, (RLastDE - dT1) * sZstepDiv); | |
| end; } | |
| RLastStepWidth := dTmp; | |
| ZZ := ZZ + dTmp; | |
| mAddVecWeight(@PIt3Dex.C1, @MarchVec, dTmp); | |
| PMCTparas.msDEstop := StartDEstop * (1 + ZZ * PMCTparas.mctDEstopFactor); | |
| dTmp := PMCTparas.CalcDE(PIt3Dex, PMCTparas); | |
| if dTmp > RLastDE + RLastStepWidth then dTmp := RLastDE + RLastStepWidth; | |
| if RLastDE > dTmp + s1em30 then | |
| begin | |
| dT1 := RLastStepWidth / (RLastDE - dTmp); | |
| if dT1 < 1 then | |
| RSFmul := maxCS(s05, dT1) | |
| else | |
| RSFmul := 1; | |
| end | |
| else RSFmul := 1; | |
| end | |
| else // ##### set found ##### | |
| begin | |
| DElimited := PIt3Dex.ItResultI < PMCTparas.MaxItsResult; | |
| if PMCTparas.iDEAddSteps > 0 then | |
| begin | |
| if DElimited then | |
| RMdoBinSearch(PMCTparas, dTmp, RLastStepWidth{, RLastDE}) | |
| else | |
| RMdoBinSearchIt(PMCTparas, ZZ); | |
| end; | |
| if DElimited then RMresult := 1 else RMresult := 2; | |
| mCopyVec(@PIt3Dex.C1, @ActPos); | |
| Exit; | |
| end; | |
| until (ZZ > MaxRayLength) or PMCTparas.PCalcThreadStats.pLBcalcStop^; //or ActZpos' < 0? (frontclipping) | |
| RMresult := 0; | |
| end; | |
| end; | |
| end; | |
| procedure CalcHSsoft(PMCT: PMCTparameter; hsPsiLight: TPsiLight5; y: Integer); | |
| var itmp, iHSnr: Integer; | |
| bisPosLight: LongBool; | |
| RLastDE, RLastStepWidth, RStepFactorDiff, sTmp, ZZ2mul, ZZ, ZRsoft, ZRSmul: Single; | |
| dTmp, dT1, dMaxL, MaxLHS, ZZ2: Double; | |
| HSVec, NVec, IC: TVec3D; | |
| procedure HSminLengthToCutPlane(HVec: TPVec3D; var dLength: Double); | |
| var dT: Double; | |
| begin | |
| with PMCT^ do | |
| begin | |
| if ((iCutOptions and 1) <> 0) and (Abs(HVec[0]) > 1e-20) then | |
| begin | |
| dT := (pIt3Dext.C1 - dCOX) / HVec[0]; | |
| if (dT > 0) and (dT < dLength) then dLength := dT; | |
| end; | |
| if ((iCutOptions and 2) <> 0) and (Abs(HVec[1]) > 1e-20) then | |
| begin | |
| dT := (pIt3Dext.C2 - dCOY) / HVec[1]; | |
| if (dT > 0) and (dT < dLength) then dLength := dT; | |
| end; | |
| if ((iCutOptions and 4) <> 0) and (Abs(HVec[2]) > 1e-20) then | |
| begin | |
| dT := (pIt3Dext.C3 - dCOZ) / HVec[2]; | |
| if (dT > 0) and (dT < dLength) then dLength := dT; | |
| end; | |
| end; | |
| end; | |
| begin | |
| with PMCT^ do | |
| begin | |
| ZZ := Abs(mZZ); | |
| iHSnr := 0; | |
| for itmp := 0 to 5 do if (calcHardShadow and (4 shl itmp)) <> 0 then | |
| iHSnr := PLVals.SortTab[itmp]; | |
| mCopyVec(@HSVec, @HSvecs[iHSnr]); | |
| bisPosLight := (PLVals.iLightPos[iHSnr] and 1) <> 0; | |
| if bisPosLight then | |
| begin //poslight scale with distance... | |
| if (PLVals.iLightPos[iHSnr] and 6) = 2 then ZRSmul := 70 / SoftShadowRadius | |
| else ZRSmul := 40 / SoftShadowRadius; | |
| end | |
| else ZRSmul := 80 / SoftShadowRadius; //+ scale with y amount | |
| hsPsiLight.Shadow := hsPsiLight.Shadow or $FC00; | |
| MaxLHS := (iMandWidth + y) * 0.6 * (1 + s05 * MinCD(ZZ, Zend * 0.4) * Clamp0D(FOVy) / iMandHeight) * sHSmaxLengthMultiplier; | |
| ZZ2 := mZZ; | |
| msDEstop := DEstop * (1 + ZZ * mctDEstopFactor); | |
| dMaxL := MaxLHS; | |
| if bisPosLight then //calculate LightVec from position | |
| begin | |
| HSVec := SubtractVectors(AddSVec2Vec3(@PLVals.PLValigned.LN[iHSnr], @Xmit), @pIt3Dext.C1); | |
| dTmp := SqrLengthOfVec(HSVec); | |
| if dTmp > PLVals.sLmaxL[iHSnr] * sHSmaxLengthMultiplier then Exit; | |
| if dTmp < Sqr(dMaxL * StepWidth) then dMaxL := Sqrt(dTmp) / StepWidth; | |
| NormaliseVectorTo(-StepWidth, @HSVec); | |
| end; | |
| ZZ2mul := -DotOfVectorsNormalize(@HSVec, @mVgradsFOV); | |
| if iCutOptions <> 0 then HSminLengthToCutPlane(@HSVec, dMaxL); | |
| if dMaxL > 0 then | |
| begin | |
| NVec := MakeDVecFromNormals(hsPsiLight); | |
| RotateVectorReverse(@NVec, @VGrads); | |
| if DotOfVectors(@NVec, @HSVec) > 0 then | |
| begin | |
| hsPsiLight.Shadow := hsPsiLight.Shadow and $3FF; | |
| Exit; | |
| end; | |
| mCopyVec(@IC, @pIt3Dext.C1); | |
| dT1 := dMaxL; | |
| ZRsoft := 1; | |
| RStepFactorDiff := 1; | |
| dTmp := CalcDE(pIt3Dext, PMCT); | |
| repeat | |
| RLastDE := dTmp; | |
| RLastStepWidth := MinCS(dTmp * sZstepDiv * RStepFactorDiff, MaxCS(msDEstop, 0.4) * mctMH04ZSD); | |
| dT1 := dT1 - RLastStepWidth; | |
| mAddVecWeight(@pIt3Dext.C1, @HSVec, -RLastStepWidth); | |
| ZZ2 := ZZ2 + RLastStepWidth * ZZ2mul; | |
| msDEstop := DEstop * (1 + Abs(ZZ2) * mctDEstopFactor); | |
| dTmp := CalcDE(pIt3Dext, PMCT); | |
| ZRsoft := MinCS(ZRsoft, (dTmp - msDEStop) * ZRSmul / (dMaxL - dT1 + s011) | |
| + Sqr(Sqr(Sqr((dMaxL - dT1) / MaxLHS)))); //.. + threshold based on lastDE, cant decrease more than...? | |
| if (pIt3Dext.ItResultI >= MaxItsResult) or (dTmp < msDEstop) then Break; | |
| if dTmp > RLastDE + RLastStepWidth then dTmp := RLastDE + RLastStepWidth; | |
| if RLastDE > dTmp + 1e-30 then | |
| begin | |
| sTmp := RLastStepWidth / (RLastDE - dTmp); | |
| if sTmp < 1 then | |
| RStepFactorDiff := maxCS(s05, sTmp) | |
| else | |
| RStepFactorDiff := 1; | |
| end | |
| else RStepFactorDiff := 1; | |
| until dT1 < 0; | |
| hsPsiLight.Shadow := (hsPsiLight.Shadow and $3FF) or (Round(Clamp01S(ZRsoft) * 63.4) shl 10); | |
| mCopyVec(@pIt3Dext.C1, @IC); | |
| end; | |
| end; | |
| end; | |
| procedure CalcHS(PMCT: PMCTparameter; hsPsiLight: TPsiLight5; y: Integer); | |
| var itmp, itmp2: Integer; | |
| RLastDE, RLastStepWidth, RStepFactorDiff, sTmp, ZZ2mul, ZZ: Single; | |
| dTmp, dT1, MaxLHS, ZZ2: Double; | |
| IC, HSVec: TVec3D; | |
| procedure HSminLengthToCutPlane(HVec: TPVec3D; var dLength: Double); | |
| var dT: Double; | |
| begin | |
| with PMCT^ do | |
| begin | |
| if ((iCutOptions and 1) <> 0) and (Abs(HVec[0]) > 1e-20) then | |
| begin | |
| dT := (pIt3Dext.C1 - dCOX) / HVec[0]; | |
| if (dT > 0) and (dT < dLength) then dLength := dT; | |
| end; | |
| if ((iCutOptions and 2) <> 0) and (Abs(HVec[1]) > 1e-20) then | |
| begin | |
| dT := (pIt3Dext.C2 - dCOY) / HVec[1]; | |
| if (dT > 0) and (dT < dLength) then dLength := dT; | |
| end; | |
| if ((iCutOptions and 4) <> 0) and (Abs(HVec[2]) > 1e-20) then | |
| begin | |
| dT := (pIt3Dext.C3 - dCOZ) / HVec[2]; | |
| if (dT > 0) and (dT < dLength) then dLength := dT; | |
| end; | |
| end; | |
| end; | |
| begin | |
| with PMCT^ do | |
| begin | |
| if (CalcHardShadow and 256) <> 0 then | |
| begin | |
| CalcHSsoft(PMCT, hsPsiLight, y); | |
| Exit; | |
| end; | |
| ZZ := Abs(mZZ); | |
| mCopyVec(@IC, @pIt3Dext.C1); | |
| hsPsiLight.Shadow := hsPsiLight.Shadow and (((calcHardShadow and $FC) shl 8) xor $FFFF); //Reset all selected HS to 0 | |
| MaxLHS := (iMandWidth + y) * 0.6 * (1 + s05 * MinCD(ZZ, Zend * 0.4) * Clamp0D(FOVy) / iMandHeight) * sHSmaxLengthMultiplier; | |
| for itmp := 0 to 5 do if (calcHardShadow and (4 shl itmp)) > 0 then | |
| begin | |
| itmp2 := PLVals.SortTab[itmp]; | |
| mCopyVec(@pIt3Dext.C1, @IC); | |
| ZZ2 := mZZ; | |
| msDEstop := DEstop * (1 + ZZ * mctDEstopFactor); | |
| dT1 := MaxLHS; | |
| if (PLVals.iLightPos[itmp2] and 1) <> 0 then //calculate LightVec from position | |
| begin | |
| HSVec := SubtractVectors(AddSVec2Vec3(@PLVals.PLValigned.LN[itmp2], @Xmit), @pIt3Dext.C1); | |
| dTmp := SqrLengthOfVec(HSVec); | |
| if dTmp > PLVals.sLmaxL[itmp2] * sHSmaxLengthMultiplier then | |
| begin | |
| hsPsiLight.Shadow := hsPsiLight.Shadow or ($400 shl itmp); | |
| Continue; | |
| end; | |
| if dTmp < Sqr(dT1 * StepWidth) then dT1 := Sqrt(dTmp) / StepWidth; | |
| HSvecs[itmp2] := NormaliseVectorTo(-StepWidth, HSVec); | |
| end; | |
| ZZ2mul := -DotOfVectorsNormalize(@HSvecs[itmp2], @mVgradsFOV); | |
| if iCutOptions <> 0 then HSminLengthToCutPlane(@HSvecs[itmp2], dT1); | |
| if dT1 > 0 then | |
| begin | |
| HSVec := MakeDVecFromNormals(hsPsiLight); | |
| RotateVectorReverse(@HSVec, @VGrads); | |
| if DotOfVectors(@HSVec, @HSvecs[itmp2]) > 0 then | |
| begin | |
| hsPsiLight.Shadow := hsPsiLight.Shadow or ($400 shl itmp); | |
| Continue; | |
| end; | |
| RStepFactorDiff := 1; | |
| dTmp := CalcDE(pIt3Dext, PMCT); | |
| repeat | |
| RLastDE := dTmp; | |
| dTmp := MinCS(dTmp * sZstepDiv * RStepFactorDiff, MaxCS(msDEstop, 0.4) * mctMH04ZSD); | |
| RLastStepWidth := dTmp; | |
| dT1 := dT1 - dTmp; | |
| mAddVecWeight(@pIt3Dext.C1, @HSvecs[itmp2], -dTmp); | |
| ZZ2 := ZZ2 + dTmp * ZZ2mul; | |
| msDEstop := DEstop * (1 + Abs(ZZ2) * mctDEstopFactor); | |
| dTmp := CalcDE(pIt3Dext, PMCT); | |
| if (pIt3Dext.ItResultI >= MaxItsResult) or (dTmp < msDEstop) then Break; | |
| if dTmp > RLastDE + RLastStepWidth then dTmp := RLastDE + RLastStepWidth; | |
| if RLastDE > dTmp + 1e-30 then | |
| begin | |
| sTmp := RLastStepWidth / (RLastDE - dTmp); | |
| if sTmp < 1 then | |
| RStepFactorDiff := maxCS(s05, sTmp) | |
| else | |
| RStepFactorDiff := 1; | |
| end | |
| else RStepFactorDiff := 1; | |
| until dT1 < 0; | |
| if dT1 > 0 then hsPsiLight.Shadow := hsPsiLight.Shadow or ($400 shl itmp); | |
| end; | |
| end; | |
| mCopyVec(@pIt3Dext.C1, @IC); | |
| end; | |
| end; | |
| //0..1 | |
| {function GetMapPixelSV(x, y: Single; LMap: TPLightMap): TSVec; | |
| var xf, yf, ipos: Integer; | |
| xs, ys, xx, yy: Double; | |
| cv: T4Cardinal; | |
| sv: T4SVec; | |
| begin | |
| with LMap^ do | |
| if LMWidth > 0 then | |
| begin | |
| xx := MinMaxCS(0, x * sLMXfactor, sLMXfactor); | |
| yy := MinMaxCS(0, y * sLMYfactor, sLMYfactor); | |
| xf := Min(LMWidth - 1, Trunc(xx)); | |
| yf := Min(LMHeight - 1, Trunc(yy)); | |
| xs := xx - xf; //lin | |
| ys := (yy - yf) * s1d255; | |
| yy := s1d255 - ys; | |
| // xs := xx - xf; //cos approx: | |
| // if xs > 0.5 then xs := 1 - Sqr(1 - xs) * 2 else xs := Sqr(xs) * 2; | |
| // ys := yy - yf; | |
| // if ys > 0.5 then ys := (1 - Sqr(1 - ys) * 2) * s1d255 | |
| // else ys := Sqr(ys) * 2 * s1d255; | |
| // yy := s1d255 - ys; | |
| ipos := iLMstart + iLMYinc * yf + xf * 4; | |
| cv[0] := PCardinal(ipos)^; | |
| cv[1] := PCardinal(ipos + 4)^; | |
| cv[2] := PCardinal(ipos + iLMYinc)^; | |
| cv[3] := PCardinal(ipos + iLMYinc + 4)^; | |
| sv := ColToSVecFlipRBc4(cv); | |
| Result[0] := (sv[0][0] + (sv[1][0] - sv[0][0]) * xs) * yy + (sv[2][0] + (sv[3][0] - sv[2][0]) * xs) * ys; | |
| Result[1] := (sv[0][1] + (sv[1][1] - sv[0][1]) * xs) * yy + (sv[2][1] + (sv[3][1] - sv[2][1]) * xs) * ys; | |
| Result[2] := (sv[0][2] + (sv[1][2] - sv[0][2]) * xs) * yy + (sv[2][2] + (sv[3][2] - sv[2][2]) * xs) * ys; | |
| end; | |
| end; } | |
| { // eax edx ecx | |
| function GetMapPixelSphere(PVec3D: TPVec3D; MapNr: Integer): TVec3D; //linear ipol | |
| var n: Integer; | |
| dv: TVec3D; | |
| xf, yf, ipos: Integer; | |
| x, y, xs, ys, xx, yy: Double;//Single; | |
| cv: T4Cardinal; | |
| sv: T4SVec; | |
| begin | |
| n := 0; | |
| repeat | |
| if CalcMaps[n].LMnumber = MapNr then Break else | |
| if CalcMaps[n].LMnumber = 0 then | |
| if LoadLightMapNr(MapNr, @CalcMaps[n]) then Break; | |
| Inc(n); | |
| until n > 2; | |
| if n > 2 then | |
| begin | |
| ClearDVec(Result); | |
| Exit; | |
| end; | |
| dv := NormaliseVector(PVec3D); | |
| x := ArcTan2(dv[0], dv[1]) * MPi05d + s05; | |
| y := s05 - ArcSin(dv[2]) * Pi1d; | |
| with CalcMaps[n] do | |
| if LMWidth > 0 then | |
| begin | |
| xx := MinMaxCS(0, x * sLMXfactor, sLMXfactor); | |
| yy := MinMaxCS(0, y * sLMYfactor, sLMYfactor); | |
| xf := Trunc(xx); | |
| xs := xx - xf; | |
| if xf = LMWidth then xf := 0; | |
| yf := Trunc(yy); | |
| if yf >= LMHeight - 1 then begin yf := LMHeight - 1; ys := 0; end else | |
| ys := yy - yf; | |
| { xs := xx - xf; //lin | |
| ys := (yy - yf) * s1d255; | |
| yy := s1d255 - ys; | |
| { xs := 0.5 - 0.5 * Cos(Pi * (xx - xf)); //test cos interpol: | |
| ys := (0.5 - 0.5 * Cos(Pi * (yy - yf))) * s1d255; | |
| yy := s1d255 - ys; } | |
| //cos approx: | |
| { if xs > 0.5 then xs := 1 - Sqr(1 - xs) * 2 else xs := Sqr(xs) * 2; | |
| if ys > 0.5 then ys := (1 - Sqr(1 - ys) * 2) * s1d255 | |
| else ys := Sqr(ys) * 2 * s1d255; | |
| yy := s1d255 - ys; | |
| ipos := iLMstart + iLMYinc * yf + xf * 4; | |
| cv[0] := PCardinal(ipos)^; | |
| cv[1] := PCardinal(ipos + 4)^; | |
| cv[2] := PCardinal(ipos + iLMYinc)^; | |
| cv[3] := PCardinal(ipos + iLMYinc + 4)^; | |
| sv := ColToSVecFlipRBc4(cv); | |
| Result[0] := (sv[0][0] + (sv[1][0] - sv[0][0]) * xs) * yy + (sv[2][0] + (sv[3][0] - sv[2][0]) * xs) * ys; | |
| Result[1] := (sv[0][1] + (sv[1][1] - sv[0][1]) * xs) * yy + (sv[2][1] + (sv[3][1] - sv[2][1]) * xs) * ys; | |
| Result[2] := (sv[0][2] + (sv[1][2] - sv[0][2]) * xs) * yy + (sv[2][2] + (sv[3][2] - sv[2][2]) * xs) * ys; | |
| end | |
| else ClearDVec(Result); | |
| end; } | |
| { // eax edx ecx | |
| function GetMapPixelSphereBicubic(PVec3D: TPVec3D; MapNr: Integer): TVec3D; | |
| var n: Integer; | |
| nx1, nx2, nx3: Integer; | |
| dv: TVec3D; | |
| xf, yf, ipos: Integer; | |
| x, y, xs, ys, xx, yy: Double; | |
| x0, x1, x2, x3, y0, y1, y2, y3: Single; | |
| cv: T4Cardinal; | |
| sv, svy: T4SVec; | |
| begin | |
| n := 0; | |
| repeat | |
| if CalcMaps[n].LMnumber = MapNr then Break else | |
| if CalcMaps[n].LMnumber = 0 then | |
| if LoadLightMapNr(MapNr, @CalcMaps[n]) then Break; | |
| Inc(n); | |
| until n > 2; | |
| if n > 2 then | |
| begin | |
| ClearDVec(Result); | |
| Exit; | |
| end; | |
| dv := NormaliseVector(PVec3D); | |
| x := ArcTan2(dv[0], dv[1]) * MPi05d + s05; | |
| y := s05 - ArcSin(dv[2]) * Pi1d; | |
| with CalcMaps[n] do | |
| if LMWidth > 0 then | |
| begin | |
| xx := MinMaxCS(0, x * sLMXfactor, sLMXfactor); | |
| yy := MinMaxCS(0, y * sLMYfactor, sLMYfactor); | |
| xf := Trunc(xx); | |
| xs := xx - xf; | |
| yf := Trunc(yy); | |
| ys := yy - yf; | |
| x0 := ((-0.8 * xs + 3.2) * (xs + 1) - 6.4) * (xs + 1) + 3.2; | |
| x1 := (1.2 * xs - 2.2) * Sqr(xs) + 1; | |
| x2 := (-1.2 * xs - 1) * Sqr(1 - xs) + 1; | |
| x3 := ((0.8 * xs + 2.4) * (2 - xs) - 6.4) * (2 - xs) + 3.2; | |
| y0 := ((-0.8 * ys + 3.2) * (ys + 1) - 6.4) * (ys + 1) + 3.2; | |
| y1 := (1.2 * ys - 2.2) * Sqr(ys) + 1; | |
| y2 := (-1.2 * ys - 1) * Sqr(1 - ys) + 1; | |
| y3 := ((0.8 * ys + 2.4) * (2 - ys) - 6.4) * (2 - ys) + 3.2; | |
| if xf > 0 then nx1 := -4 else nx1 := (LMWidth - 1) * 4; | |
| if xf < LMWidth - 1 then nx2 := 8 else nx2 := (2 - LMWidth) * 4; | |
| if xf < LMWidth then nx3 := 4 else nx3 := (1 - LMWidth) * 4; | |
| if yf > 0 then Dec(yf) else Inc(yf, LMHeight - 1); | |
| xf := iLMstart + xf * 4; | |
| ipos := xf + iLMYinc * yf; | |
| cv[0] := PCardinal(ipos + nx1)^; | |
| cv[1] := PCardinal(ipos)^; | |
| cv[2] := PCardinal(ipos + nx3)^; | |
| cv[3] := PCardinal(ipos + nx2)^; | |
| sv := ColToSVecFlipRBc4(cv); | |
| svy[0][0] := sv[0][0] * x0 + sv[1][0] * x1 + sv[2][0] * x2 + sv[3][0] * x3; | |
| svy[0][1] := sv[0][1] * x0 + sv[1][1] * x1 + sv[2][1] * x2 + sv[3][1] * x3; | |
| svy[0][2] := sv[0][2] * x0 + sv[1][2] * x1 + sv[2][2] * x2 + sv[3][2] * x3; | |
| if yf < LMHeight - 1 then | |
| begin | |
| Inc(yf); | |
| Inc(ipos, iLMYinc); | |
| end else begin | |
| yf := 0; | |
| ipos := xf; | |
| end; | |
| cv[0] := PCardinal(ipos + nx1)^; | |
| cv[1] := PCardinal(ipos)^; | |
| cv[2] := PCardinal(ipos + nx3)^; | |
| cv[3] := PCardinal(ipos + nx2)^; | |
| sv := ColToSVecFlipRBc4(cv); | |
| svy[1][0] := sv[0][0] * x0 + sv[1][0] * x1 + sv[2][0] * x2 + sv[3][0] * x3; | |
| svy[1][1] := sv[0][1] * x0 + sv[1][1] * x1 + sv[2][1] * x2 + sv[3][1] * x3; | |
| svy[1][2] := sv[0][2] * x0 + sv[1][2] * x1 + sv[2][2] * x2 + sv[3][2] * x3; | |
| if yf < LMHeight - 1 then | |
| begin | |
| Inc(yf); | |
| Inc(ipos, iLMYinc); | |
| end else begin | |
| yf := 0; | |
| ipos := xf; | |
| end; | |
| cv[0] := PCardinal(ipos + nx1)^; | |
| cv[1] := PCardinal(ipos)^; | |
| cv[2] := PCardinal(ipos + nx3)^; | |
| cv[3] := PCardinal(ipos + nx2)^; | |
| sv := ColToSVecFlipRBc4(cv); | |
| svy[2][0] := sv[0][0] * x0 + sv[1][0] * x1 + sv[2][0] * x2 + sv[3][0] * x3; | |
| svy[2][1] := sv[0][1] * x0 + sv[1][1] * x1 + sv[2][1] * x2 + sv[3][1] * x3; | |
| svy[2][2] := sv[0][2] * x0 + sv[1][2] * x1 + sv[2][2] * x2 + sv[3][2] * x3; | |
| if yf < LMHeight - 1 then Inc(ipos, iLMYinc) else ipos := xf; | |
| cv[0] := PCardinal(ipos + nx1)^; | |
| cv[1] := PCardinal(ipos)^; | |
| cv[2] := PCardinal(ipos + nx3)^; | |
| cv[3] := PCardinal(ipos + nx2)^; | |
| sv := ColToSVecFlipRBc4(cv); | |
| svy[3][0] := sv[0][0] * x0 + sv[1][0] * x1 + sv[2][0] * x2 + sv[3][0] * x3; | |
| svy[3][1] := sv[0][1] * x0 + sv[1][1] * x1 + sv[2][1] * x2 + sv[3][1] * x3; | |
| svy[3][2] := sv[0][2] * x0 + sv[1][2] * x1 + sv[2][2] * x2 + sv[3][2] * x3; | |
| Result[0] := (svy[0][0] * y0 + svy[1][0] * y1 + svy[2][0] * y2 + svy[3][0] * y3) * s1d255; | |
| Result[1] := (svy[0][1] * y0 + svy[1][1] * y1 + svy[2][1] * y2 + svy[3][1] * y3) * s1d255; | |
| Result[2] := (svy[0][2] * y0 + svy[1][2] * y1 + svy[2][2] * y2 + svy[3][2] * y3) * s1d255; | |
| end | |
| else ClearDVec(Result); | |
| end; } | |
| //function GetLightMapPixel(const x, y: Single; LM: TPLightMap; bSqr: LongBool; WrapAround: Integer): TSVec; | |
| function SplineIpolMap(x, y: Double; PCalcMap: TPLightMap): TVec3D; //x,y direct map coords | |
| var nx1, nx2, nx3, xf, yf, ipos, il, im: Integer; | |
| cv: T4Cardinal; | |
| xv, yv: TSVec; | |
| sv: T4SVec; | |
| svy: T3SVec; | |
| fCol2SVec: TCol2SVec; | |
| fCol2SVecPas: TCol2SVecX87; | |
| begin | |
| // Result := SVecToDVec(GetLightMapPixel(x / PCalcMap.sLMXfactor, y / PCalcMap.sLMYfactor, PCalcMap, False, 1)); | |
| // Exit; | |
| with PCalcMap^ do | |
| begin | |
| xf := Trunc(x); | |
| yf := Trunc(y); | |
| xv := MakeSplineCoeff(x - xf); | |
| yv := MakeSplineCoeff(y - yf); | |
| if iMapType = 1 then im := 6 else im := 4; | |
| il := (LMWidth + 1) * im; | |
| if yf > 0 then Dec(yf) else Inc(yf, LMHeight - 1); | |
| if xf > 0 then nx1 := -im else nx1 := (LMWidth - 1) * im; | |
| if xf < LMWidth - 1 then nx2 := im * 2 else nx2 := (2 - LMWidth) * im; | |
| if xf < LMWidth then nx3 := im else nx3 := (1 - LMWidth) * im; | |
| xf := iLMstart + xf * im; | |
| ipos := xf + il * yf; | |
| cv[0] := ipos + nx1; | |
| cv[1] := ipos; | |
| cv[2] := ipos + nx3; | |
| cv[3] := ipos + nx2; | |
| if SupportSSE2 then | |
| begin | |
| if im = 6 then fCol2SVec := ColToSVecSSE2_16 else fCol2SVec := ColToSVecSSE2; | |
| fCol2SVec(cv, @xv, @svy[0]); | |
| if yf < 0 then Inc(yf) else if yf < LMHeight - 1 then | |
| begin | |
| Inc(yf); | |
| Inc(ipos, il); | |
| end | |
| else | |
| begin | |
| yf := 0; | |
| ipos := xf; | |
| end; | |
| cv[0] := ipos + nx1; | |
| cv[1] := ipos; | |
| cv[2] := ipos + nx3; | |
| cv[3] := ipos + nx2; | |
| fCol2SVec(cv, @xv, @svy[1]); | |
| if yf < LMHeight - 1 then | |
| begin | |
| Inc(yf); | |
| Inc(ipos, il); | |
| end | |
| else | |
| begin | |
| yf := 0; | |
| ipos := xf; | |
| end; | |
| cv[0] := ipos + nx1; | |
| cv[1] := ipos; | |
| cv[2] := ipos + nx3; | |
| cv[3] := ipos + nx2; | |
| fCol2SVec(cv, @xv, @svy[2]); | |
| if yf < LMHeight - 1 then Inc(ipos, il) else ipos := xf; | |
| cv[0] := ipos + nx1; | |
| cv[1] := ipos; | |
| cv[2] := ipos + nx3; | |
| cv[3] := ipos + nx2; | |
| fCol2SVec(cv, @xv, @sv[0]); | |
| Result[0] := svy[0][0] * yv[0] + svy[1][0] * yv[1] + svy[2][0] * yv[2] + sv[0][0] * yv[3]; | |
| Result[1] := svy[0][1] * yv[0] + svy[1][1] * yv[1] + svy[2][1] * yv[2] + sv[0][1] * yv[3]; | |
| Result[2] := svy[0][2] * yv[0] + svy[1][2] * yv[1] + svy[2][2] * yv[2] + sv[0][2] * yv[3]; | |
| end //png alpha on 4? | |
| else | |
| begin | |
| if im = 6 then fCol2SVecPas := ColToSVecFlipRBc416 else fCol2SVecPas := ColToSVecFlipRBc4; | |
| sv := fCol2SVecPas(cv); | |
| svy[0][0] := sv[0][0] * xv[0] + sv[1][0] * xv[1] + sv[2][0] * xv[2] + sv[3][0] * xv[3]; | |
| svy[0][1] := sv[0][1] * xv[0] + sv[1][1] * xv[1] + sv[2][1] * xv[2] + sv[3][1] * xv[3]; | |
| svy[0][2] := sv[0][2] * xv[0] + sv[1][2] * xv[1] + sv[2][2] * xv[2] + sv[3][2] * xv[3]; | |
| if yf < 0 then Inc(yf) else if yf < LMHeight - 1 then | |
| begin | |
| Inc(yf); | |
| Inc(ipos, il); | |
| end | |
| else | |
| begin | |
| yf := 0; | |
| ipos := xf; | |
| end; | |
| cv[0] := ipos + nx1; | |
| cv[1] := ipos; | |
| cv[2] := ipos + nx3; | |
| cv[3] := ipos + nx2; | |
| sv := fCol2SVecPas(cv); | |
| svy[1][0] := sv[0][0] * xv[0] + sv[1][0] * xv[1] + sv[2][0] * xv[2] + sv[3][0] * xv[3]; | |
| svy[1][1] := sv[0][1] * xv[0] + sv[1][1] * xv[1] + sv[2][1] * xv[2] + sv[3][1] * xv[3]; | |
| svy[1][2] := sv[0][2] * xv[0] + sv[1][2] * xv[1] + sv[2][2] * xv[2] + sv[3][2] * xv[3]; | |
| if yf < LMHeight - 1 then | |
| begin | |
| Inc(yf); | |
| Inc(ipos, il); | |
| end | |
| else | |
| begin | |
| yf := 0; | |
| ipos := xf; | |
| end; | |
| cv[0] := ipos + nx1; | |
| cv[1] := ipos; | |
| cv[2] := ipos + nx3; | |
| cv[3] := ipos + nx2; | |
| sv := fCol2SVecPas(cv); | |
| svy[2][0] := sv[0][0] * xv[0] + sv[1][0] * xv[1] + sv[2][0] * xv[2] + sv[3][0] * xv[3]; | |
| svy[2][1] := sv[0][1] * xv[0] + sv[1][1] * xv[1] + sv[2][1] * xv[2] + sv[3][1] * xv[3]; | |
| svy[2][2] := sv[0][2] * xv[0] + sv[1][2] * xv[1] + sv[2][2] * xv[2] + sv[3][2] * xv[3]; | |
| if yf < LMHeight - 1 then Inc(ipos, il) else ipos := xf; | |
| cv[0] := ipos + nx1; | |
| cv[1] := ipos; | |
| cv[2] := ipos + nx3; | |
| cv[3] := ipos + nx2; | |
| sv := fCol2SVecPas(cv); | |
| Result[0] := (svy[0][0] * yv[0] + svy[1][0] * yv[1] + svy[2][0] * yv[2] + | |
| (sv[0][0] * xv[0] + sv[1][0] * xv[1] + sv[2][0] * xv[2] + sv[3][0] * xv[3]) * yv[3]) * s1d255; | |
| Result[1] := (svy[0][1] * yv[0] + svy[1][1] * yv[1] + svy[2][1] * yv[2] + | |
| (sv[0][1] * xv[0] + sv[1][1] * xv[1] + sv[2][1] * xv[2] + sv[3][1] * xv[3]) * yv[3]) * s1d255; | |
| Result[2] := (svy[0][2] * yv[0] + svy[1][2] * yv[1] + svy[2][2] * yv[2] + | |
| (sv[0][2] * xv[0] + sv[1][2] * xv[1] + sv[2][2] * xv[2] + sv[3][2] * xv[3]) * yv[3]) * s1d255; | |
| end; | |
| end; | |
| end; | |
| // eax edx ecx | |
| function GetMapPixelSphereSpline(PVec3D: TPVec3D; MapNr: Integer): TVec3D; | |
| var n: Integer; | |
| dv: TVec3D; | |
| x, y: Double; | |
| begin //4 st slots might be already used by calling formula!!! | |
| n := 0; | |
| repeat | |
| if CalcMaps[n].LMnumber = MapNr then Break else | |
| if CalcMaps[n].LMnumber = 0 then | |
| if LoadLightMapNr(MapNr, @CalcMaps[n]) then Break; | |
| Inc(n); | |
| until n > 2; | |
| if n > 2 then | |
| begin | |
| MapIsMissing := True; | |
| ClearDVec(Result); | |
| Exit; | |
| end; | |
| dv := NormaliseVector(PVec3D); | |
| x := ArcTan2(dv[0], dv[1]) * MPi05d + s05; | |
| y := s05 - ArcSinSafe(dv[2]) * Pi1d; | |
| with CalcMaps[n] do | |
| begin | |
| if LMWidth > 0 then | |
| Result := SplineIpolMap(Min0MaxCD(x * sLMXfactor, sLMXfactor), | |
| Min0MaxCD(y * sLMYfactor, sLMYfactor), @CalcMaps[n]) | |
| else ClearDVec(Result); | |
| end; | |
| end; | |
| function FracA(d: Double): Double; | |
| begin | |
| if d < 0 then Result := 1 + Frac(d) | |
| else Result := Frac(d); | |
| end; | |
| { // eax edx ecx | |
| function GetMapPixelDirectXY(PVec3D: TPVec3D; MapNr: Integer): TVec3D; //Direct pixel coords 0..1 with tiling | |
| var n: Integer; | |
| xf, yf, ipos: Integer; | |
| xs, ys, xx, yy: Double; | |
| cv: T4Cardinal; | |
| sv: T4SVec; | |
| begin | |
| n := 0; | |
| repeat | |
| if CalcMaps[n].LMnumber = MapNr then Break else | |
| if CalcMaps[n].LMnumber = 0 then | |
| if LoadLightMapNr(MapNr, @CalcMaps[n]) then Break; | |
| Inc(n); | |
| until n > 2; | |
| if n > 2 then | |
| begin | |
| ClearDVec(Result); | |
| Exit; | |
| end; | |
| with CalcMaps[n] do | |
| if LMWidth > 0 then | |
| begin | |
| xx := FracA(PVec3D^[0]) * sLMXfactor; | |
| yy := FracA(PVec3D^[1]) * sLMYfactor; | |
| xf := Trunc(xx); | |
| xs := xx - xf; | |
| if xf = LMWidth then xf := 0; | |
| yf := Trunc(yy); | |
| ys := yy - yf; | |
| if yf = LMHeight then yf := 0; | |
| //cos approx: | |
| if xs > 0.5 then xs := 1 - Sqr(1 - xs) * 2 else xs := Sqr(xs) * 2; | |
| if ys > 0.5 then ys := (1 - Sqr(1 - ys) * 2) * s1d255 | |
| else ys := Sqr(ys) * 2 * s1d255; | |
| yy := s1d255 - ys; | |
| ipos := iLMstart + iLMYinc * yf + xf * 4; | |
| cv[0] := PCardinal(ipos)^; | |
| cv[1] := PCardinal(ipos + 4)^; | |
| cv[2] := PCardinal(ipos + iLMYinc)^; | |
| cv[3] := PCardinal(ipos + iLMYinc + 4)^; | |
| sv := ColToSVecFlipRBc4(cv); | |
| Result[0] := (sv[0][0] + (sv[1][0] - sv[0][0]) * xs) * yy + (sv[2][0] + (sv[3][0] - sv[2][0]) * xs) * ys; | |
| Result[1] := (sv[0][1] + (sv[1][1] - sv[0][1]) * xs) * yy + (sv[2][1] + (sv[3][1] - sv[2][1]) * xs) * ys; | |
| Result[2] := (sv[0][2] + (sv[1][2] - sv[0][2]) * xs) * yy + (sv[2][2] + (sv[3][2] - sv[2][2]) * xs) * ys; | |
| end | |
| else ClearDVec(Result); | |
| end; } | |
| // eax edx ecx | |
| function GetMapPixelDirectXYspline(PVec3D: TPVec3D; MapNr: Integer): TVec3D; //Direct pixel coords 0..1 with tiling | |
| var n: Integer; | |
| x, y: Double; | |
| begin | |
| n := 0; | |
| repeat | |
| if CalcMaps[n].LMnumber = MapNr then Break else | |
| if CalcMaps[n].LMnumber = 0 then | |
| if LoadLightMapNr(MapNr, @CalcMaps[n]) then Break; | |
| Inc(n); | |
| until n > 2; | |
| if n > 2 then | |
| begin | |
| MapIsMissing := True; | |
| ClearDVec(Result); | |
| Exit; | |
| end; | |
| with CalcMaps[n] do | |
| if LMWidth > 0 then | |
| begin | |
| x := FracA(PVec3D^[0]) * sLMXfactor; | |
| y := FracA(PVec3D^[1]) * sLMYfactor; | |
| Result := SplineIpolMap(x, y, @CalcMaps[n]); | |
| end | |
| else ClearDVec(Result); | |
| end; | |
| procedure IniIt3D(PMCT: PMCTparameter; It3Dex: TPIteration3Dext); | |
| begin | |
| with PMCT^ do | |
| begin | |
| It3Dex.J4 := dJUw; | |
| It3Dex.Ju4 := dJUw; | |
| FastMove(dJUx, It3Dex.J1, 168); | |
| FastMove(dJUx, It3Dex.Ju1, 24); | |
| FastMove(Smatrix4d, It3Dex.Smatrix4, 64); | |
| FastMove(pInitialization, It3Dex.pInitialization, 24); | |
| if DEoption = 20 then It3Dex.RStopD := -1e10; | |
| It3Dex.PMapFunc := GetMapPixelSphereSpline; | |
| It3Dex.PMapFunc2 := GetMapPixelDirectXYspline; | |
| It3Dex.Deriv1 := 1; | |
| pIt3Dext := It3Dex; | |
| end; | |
| end; | |
| { it3dext: | |
| CalcSIT: ByteBool; //+148 Bool + more options | |
| RepeatFrom1:Byte; //+149 | |
| EndTo: Word; //+150 | |
| .. | |
| iRepeatFrom: Word; //+188 | |
| iStartFrom: Word; //+190 | |
| OTrap: Double; //+192 calced by m3d, minimum vector length in dIFS | |
| VaryScale: Double; //+200 to use in vary by its or in dIFS as absScale | |
| bFirstIt: Integer; //+208 used also as iteration count, is set to 0 on it-start | |
| bTmp: Integer; //+212 (used for formula count), dIFS: minDE iteration | |
| Dfree1: Double; //+216 OTrap coloring in dIFS: formula can store a value 0..8 (*4096=15bit) | |
| mct: | |
| bRepeatFrom1: Byte; //+149 | |
| wEndTo: Word; //+150 | |
| bDoJulia: LongBool; //+152 | |
| dLNRStop: Single; //+156 | |
| DEoption: Integer; //+160 RepeatFrom2, EndTo | |
| fHln: array[0..5] of Single; //esi+164 | |
| RepeatFrom: Word; //+188 | |
| StartFrom: Word; | |
| Smatrix4d: TSmatrix4; | |
| pInitialization: array[0..5] of TFormulaInitialization; | |
| {procedure RegulationUpdate(const ActDE, LastDE, LastStep: Double; var DEmul: Single); | |
| var dTmp: Double; | |
| begin | |
| if LastDE > ActDE + s1em30 then | |
| begin | |
| dTmp := LastStep / (LastDE - ActDE); | |
| if dTmp < 1 then | |
| DEmul := MaxCS(0.5, dTmp) | |
| else | |
| DEmul := 1; | |
| end | |
| else DEmul := 1; | |
| end; } | |
| // eax edx ebp+8 | |
| procedure CalcZposAndRough(siLight: TPsiLight5; mct: PMCTparameter; const ZZ: Double); | |
| {var itmp: Integer; | |
| begin | |
| with mct^ do | |
| begin | |
| itmp := Round(8388352 - ZcMul * (Sqrt(ZZ * Zcorr + 1) - 1)); | |
| if itmp < 0 then itmp := 0 else | |
| if itmp > 8388352 then itmp := 8388352; | |
| PCardinal(@siLight.RoughZposFine)^ := iTmp shl 8; | |
| if iSmNormals > 0 then | |
| siLight.RoughZposFine := siLight.RoughZposFine or Round(sRoughness * 255); | |
| end; } | |
| asm | |
| push ebx | |
| sub esp, 4 | |
| fld1 | |
| test byte [ebp + 15], 128 //negative zz clip | |
| jns @1 | |
| fldz | |
| jmp @2 | |
| @1: fld qword [ebp + 8] | |
| @2: fmul qword [edx + TMCTparameter.Zcorr] | |
| fadd st(0), st(1) | |
| fsqrt //at fsqrt? ZZ * Zcorr > 1?? zz=-642!! | |
| fsubrp //invalid fp operation in critical ipol hybrid | |
| fmul qword [edx + TMCTparameter.ZcMul] | |
| fistp dword [esp] | |
| mov ebx, 8388352 | |
| sub ebx, dword [esp] | |
| test ebx, ebx | |
| jnl @up1 | |
| xor ebx, ebx | |
| @up1: | |
| cmp ebx, 8388352 | |
| jle @up2 | |
| mov ebx, 8388352 | |
| @up2: | |
| shl ebx, 8 | |
| cmp byte [edx + TMCTparameter.iSmNormals], 0 | |
| jle @up3 | |
| fld dword [edx + TMCTparameter.sRoughness] | |
| fmul s255 | |
| fistp dword [esp] | |
| or ebx, [esp] | |
| @up3: | |
| mov [eax + 6], ebx | |
| add esp, 4 | |
| pop ebx | |
| end; | |
| procedure DelayCalcPart(ThreadCount: Integer; PCTS: TPCalcThreadStats); | |
| var Tick: Double; | |
| Event: THandle; | |
| x, y, Milliseconds: Integer; | |
| begin | |
| Milliseconds := 300; | |
| Tick := getHiQmillis + Milliseconds; | |
| Event := CreateEvent(nil, False, False, nil); | |
| try | |
| while (Milliseconds > 0) and | |
| (MsgWaitForMultipleObjects(1, Event, False, Milliseconds, QS_ALLINPUT) | |
| <> WAIT_TIMEOUT) do | |
| begin | |
| Application.ProcessMessages; | |
| if Application.Terminated or PCTS.pLBcalcStop^ then Exit; | |
| x := 0; | |
| for y := 1 to ThreadCount do if PCTS.CTrecords[y].isActive > 0 then Inc(x); | |
| if x = 0 then Milliseconds := 0 else Milliseconds := Round(Tick - getHiQmillis); | |
| if Milliseconds > 500 then Exit; | |
| end; | |
| finally | |
| CloseHandle(Event); | |
| end; | |
| end; | |
| initialization | |
| CalcMaps[0].LMnumber := 0; | |
| CalcMaps[1].LMnumber := 0; | |
| CalcMaps[2].LMnumber := 0; | |
| end. |