// This file is distributed under a BSD license. See LICENSE.txt for details. #include "_start.hpp" #include "genscene.hpp" #include "genmesh.hpp" #include "genminmesh.hpp" #include "genoverlay.hpp" #include "genmaterial.hpp" #include "geneffect.hpp" #include "genblobspline.hpp" #include "kkriegergame.hpp" #include "engine.hpp" #include #if !sPLAYER #include "winview.hpp" #endif #if sPROFILE #include "_util.hpp" sMAKEZONE(ExecWalk ,"ExecWalk " ,0xff8000d0); sMAKEZONE(PaintScene ,"PaintScene" ,0xffb040ff); sMAKEZONE(ExecXForm ,"ExecXForm" ,0xff593d33); sMAKEZONE(InstanceMat ,"InstanceMat",0xffee2121); #endif /****************************************************************************/ #if !sPLAYER KOp *ShowPortalOp; sVector ShowPortalCube[8]; sBool ShowPortalOpProcessed; sBool SceneWireframe = sFALSE; sInt SceneWireFlags = 0; sU32 SceneWireMask = 0; #endif sInt GenScenePasses = ~0; static sInt RenderPassAdjust = 0; /****************************************************************************/ #define SCRIPTVERIFY(x) {if(!(x)) return 0;} /****************************************************************************/ GenScene::GenScene() { ClassId = KC_SCENE; Childs.Init(); DrawMesh = 0; #if sLINK_KKRIEGER CollMesh = 0; #endif Effect = 0; sSetMem(SRT,0,sizeof(SRT)); SRT[0] = 1; SRT[1] = 1; SRT[2] = 1; Count = 0; Next = 0; IsSector = sFALSE; } GenScene::~GenScene() { sInt i; for(i=0;iRelease(); Childs.Exit(); if(DrawMesh) DrawMesh->Release(); #if sLINK_KKRIEGER if(CollMesh) CollMesh->Release(); #endif if(Effect) Effect->Release(); } void GenScene::Copy(KObject *o) { sInt i; GenScene *scene; sVERIFY(o->ClassId==KC_SCENE); scene = (GenScene *) o; Childs.Copy(scene->Childs); for(i=0;iAddRef(); DrawMesh = scene->DrawMesh; if(DrawMesh) DrawMesh->AddRef(); #if sLINK_KKRIEGER CollMesh = scene->CollMesh; if(CollMesh) CollMesh->AddRef(); #endif Effect = scene->Effect; if(Effect) Effect->AddRef(); sCopyMem(SRT,scene->SRT,sizeof(SRT)); Count = scene->Count; IsSector = scene->IsSector; Next = 0; } /****************************************************************************/ /****************************************************************************/ GenScene *MakeScene(KObject *in) { GenScene *scene; EngMesh *mesh; scene = 0; if(in) { if(in->ClassId==KC_SCENE) { scene = (GenScene *)in; } #if sLINK_FATMESH else if(in->ClassId==KC_MESH) { GenMesh *inMesh; scene = new GenScene; inMesh = (GenMesh *)in; if(inMesh) { inMesh->Compact(); #if !sPLAYER if(SceneWireframe) { inMesh->PrepareWire(SceneWireFlags,SceneWireMask); mesh = inMesh->WireMesh; } else { inMesh->UnPrepareWire(); inMesh->Prepare(); mesh = inMesh->PreparedMesh; } #else inMesh->Prepare(); mesh = inMesh->PreparedMesh; #endif if(mesh) { scene->DrawMesh = mesh; scene->DrawMesh->AddRef(); #if sPLAYER mesh->Preload(); #endif } #if sLINK_KKRIEGER scene->CollMesh = new KKriegerMesh(inMesh); #endif inMesh->Release(); } } #endif else if(in->ClassId==KC_EFFECT) { scene = new GenScene; scene->Effect = (GenEffect *)in; } #if sLINK_MINMESH else if(in->ClassId==KC_MINMESH) { GenMinMesh *minMesh; scene = new GenScene; minMesh = (GenMinMesh *)in; if(minMesh) { #if !sPLAYER if(SceneWireframe) { minMesh->PrepareWire(SceneWireFlags,SceneWireMask); mesh = minMesh->WireMesh; } else { minMesh->UnPrepareWire(); minMesh->Prepare(); mesh = minMesh->PreparedMesh; } #else minMesh->Prepare(); mesh = minMesh->PreparedMesh; #endif if(mesh) { scene->DrawMesh = mesh; scene->DrawMesh->AddRef(); #if sPLAYER mesh->Preload(); #endif } minMesh->Release(); } } #endif } return scene; } /****************************************************************************/ /*** ***/ /*** The Operators ***/ /*** ***/ /****************************************************************************/ void ExecSceneInput(KOp *parent,KEnvironment *kenv,sInt i) { KOp *op; GenScene *scene; EngMesh *drawMesh; sInt classId; op = parent->GetInput(i); classId = KC_NULL; #if sPLAYER if(op->CacheFreed) classId = op->Result; else #endif if(op->Cache) classId = op->Cache->ClassId; if(classId == KC_MESH || classId == KC_MINMESH || classId == KC_EFFECT) { scene = (GenScene *)parent->Cache; if(scene->Childs.Count) { sVERIFY(i < scene->Childs.Count); drawMesh = scene->Childs[i]->DrawMesh; } else drawMesh = scene->DrawMesh; if(classId == KC_MESH || classId==KC_MINMESH) { #if sLINK_KKRIEGER // this monster culling HACK should be removed. if(kenv->CurrentEvent && kenv->CurrentEvent->CullDist>0) { sVector v; v.Sub3(kenv->ExecStack.Top().l,kenv->GameCam.CameraSpace.l); if(kenv->CurrentEvent->CullDist*kenv->CurrentEvent->CullDistAddPaintJob(drawMesh,kenv->ExecStack.Top(),kenv->Var[KV_TIME].x,RenderPassAdjust); } else // effect Engine->AddPaintJob(op,kenv->ExecStack.Top(),kenv,RenderPassAdjust); } else { op->Exec(kenv); } } /****************************************************************************/ void ExecSceneInputs(KOp *parent,KEnvironment *kenv,sF32 *srt) { sInt i,max; GenScene *scene; sMatrix mat; scene = (GenScene *) parent->Cache; if(srt) { mat.InitSRT(srt); kenv->ExecStack.PushMul(mat); } max = parent->GetInputCount(); for(i=0;iExecStack.Pop(); } /****************************************************************************/ GenScene * __stdcall Init_Scene_Scene(GenMesh *mesh,sF323 s,sF323 r,sF323 t,sBool lightmap) { GenScene *scene; if(mesh==0) return new GenScene; scene = MakeScene(mesh); if(scene) sCopyMem(scene->SRT,&s.x,9*4); return scene; } void __stdcall Exec_Scene_Scene(KOp *op,KEnvironment *kenv,sF323 s,sF323 r,sF323 t,sBool lightmap) { ExecSceneInputs(op,kenv,&s.x); } /****************************************************************************/ GenScene * __stdcall Init_Scene_Add(sInt count,GenScene *s0,...) { GenScene *scene,*add; sInt i; scene = new GenScene; for(i=0;iChilds.Add() = add; } return scene; } void __stdcall Exec_Scene_Add(KOp *op,KEnvironment *kenv) { ExecSceneInputs(op,kenv,0); } GenScene * __stdcall Init_Scene_Select(sInt select,sInt count,GenScene *s0,...) { GenScene *scene,*add; sInt i; scene = new GenScene; for(i=0;iChilds.Add() = add; } return scene; } void __stdcall Exec_Scene_Select(KOp *op,KEnvironment *kenv) { sInt max = op->GetInputCount(); if(max>0) ExecSceneInput(op,kenv,sFtol(*op->GetAnimPtrF(0))%max); } /****************************************************************************/ GenScene * __stdcall Init_Scene_Multiply(GenScene *add,sF323 s,sF323 r,sF323 t,sInt count) { GenScene *scene; add = MakeScene(add); if(!add) return 0; scene = new GenScene; *scene->Childs.Add() = add; scene->Count = count; sCopyMem(scene->SRT,&s.x,9*4); return scene; } void __stdcall Exec_Scene_Multiply(KOp *op,KEnvironment *kenv,sF323 s,sF323 r,sF323 t,sInt count) { sMatrix mat,mat2; sInt i; sVector save; kenv->ExecStack.Dup(); mat.InitSRT(&s.x); save = kenv->Var[KV_SELECT]; for(i=0;iVar[KV_SELECT].Init(i,i,i,i); ExecSceneInputs(op,kenv,0); mat2.MulA(mat,kenv->ExecStack.Top()); kenv->ExecStack.Pop(); kenv->ExecStack.Push(mat2); } kenv->ExecStack.Pop(); kenv->Var[KV_SELECT] = save; } /****************************************************************************/ GenScene * __stdcall Init_Scene_Transform(GenScene *add,sF323 s,sF323 r,sF323 t) { return Init_Scene_Multiply(add,s,r,t,0); } void __stdcall Exec_Scene_Transform(KOp *op,KEnvironment *kenv,sF323 s,sF323 r,sF323 t) { ExecSceneInputs(op,kenv,&s.x); } /****************************************************************************/ GenScene * __stdcall Init_Scene_Light(sF323 r,sF323 t,sU32 flags,sF32 zoom,sU32 color,sF32 amplify,sF32 range) { return new GenScene; } void __stdcall Exec_Scene_Light(KOp *op,KEnvironment *kenv,sF323 r,sF323 t,sU32 flags,sF32 zoom,sU32 color,sF32 amplify,sF32 range) { //KSceneJob *job; sF32 srt[9]; sMatrix mat;//,mat2; // sVERIFY(op->GetInputCount()==0); srt[0] = 1; srt[1] = 1; srt[2] = 1; srt[3] = r.x; srt[4] = r.y; srt[5] = r.z; srt[6] = t.x; srt[7] = t.y; srt[8] = t.z; mat.InitSRT(srt); kenv->ExecStack.PushMul(mat); //mat2.Mul4(mat,kenv->ExecMatrix); #if !sPLAYER if(ShowPortalOp == op) { ShowPortalCube[0] = kenv->ExecStack.Top().l; ShowPortalOpProcessed = sTRUE; } #endif EngLight light; light.Type = (flags & 4) ? sLT_DIRECTIONAL : sLT_POINT; light.Position = kenv->ExecStack.Top().l; light.Direction = kenv->ExecStack.Top().k; if(!range && (flags & 4)) light.Position.Scale4(light.Direction,1e+6f); light.Flags = flags; // ignore zoom light.Color = color; light.Amplify = amplify; light.Range = range ? range : 1e+15f; light.Event = kenv->CurrentEvent; light.Id = (sInt) op; Engine->AddLightJob(light); kenv->ExecStack.Pop(); } /****************************************************************************/ GenScene * __stdcall Init_Scene_Camera(sF323 s,sF323 r,sF323 t) { GenScene *scene; scene = new GenScene; sCopyMem(scene->SRT,&s.x,9*4); return scene; } void __stdcall Exec_Scene_Camera(KOp *op,KEnvironment *kenv,sF323 s,sF323 r,sF323 t) { sMatrix mat; #if !sPLAYER if(!GenOverlayManager->LinkEdit) { mat.InitSRT(&s.x); kenv->GameCam.CameraSpace.MulA(mat,kenv->ExecStack.Top()); } #else { mat.InitSRT(&s.x); kenv->GameCam.CameraSpace.MulA(mat,kenv->ExecStack.Top()); } #endif } /****************************************************************************/ GenScene * __stdcall Init_Scene_Limb(GenScene *scene0,GenScene *scene1,sF323 pos,sF323 dir,sF32 l0,sF32 l1,sU32 flags) { GenScene *scene; GenScene *add; scene = new GenScene(); add = MakeScene(scene0); if(add) *scene->Childs.Add() = add; add = MakeScene(scene1); if(add) *scene->Childs.Add() = add; return scene; } void __stdcall Exec_Scene_Limb(KOp *op,KEnvironment *kenv,sF323 pos,sF323 dirv,sF32 a,sF32 b,sU32 flags) { sMatrix mat0,mat1,var; sF32 c,s,t; sVector i,j,k; // flags &= ~2; // relative mode ist kaputt if(op->GetInputCount()==2) { const sMatrix &matrix = kenv->ExecStack.Top(); if(!(flags&2)) { pos.x -= matrix.l.x; pos.y -= matrix.l.y; pos.z -= matrix.l.z; } j.Init(-pos.x,-pos.y,-pos.z,0); // t-direction i.Init(dirv.x,dirv.y,dirv.z,0); if(!(flags&2)) i.Rotate3(matrix); k.Cross4(i,j); // cross vector i.Cross4(j,k); // s-direction c = j.Abs3(); // length i.Unit3(); j.Unit3(); k.Unit3(); t = (c*c+a*a-b*b)/(2*c); // b²=c²+a²-2ca cos(ß); t=a cos(ß); /*if(a<=t) s=0; else s = sFSqrt(a*a-t*t);*/ s = (a-t) * (a+t); if(s <= 0.0f) s = 0.0f; else s = sFSqrt(s); mat0.k = k; mat0.j.Scale4(j,t); mat0.j.AddScale3(i,s); mat0.j.Unit3(); mat0.i.Cross4(mat0.j,mat0.k); mat0.l.Init4(0,0,0,1); if(a<=t && !(flags&1)) { mat1 = mat0; mat1.l.AddScale3(j,-a-b); } else { mat1.k = k; mat1.j.Scale4(j,c-t); mat1.j.AddScale3(i,-s); mat1.j.Unit3(); mat1.i.Cross4(mat1.j,mat1.k); mat1.l.Init4(pos.x,pos.y,pos.z,1); } if(flags&2) kenv->ExecStack.PushMul(mat0); else { kenv->ExecStack.Push(mat0); kenv->ExecStack.Top().l.Add3(matrix.l); } kenv->SetMatrix(mat1,var); ExecSceneInput(op,kenv,0); //op->ExecInput(kenv,0); kenv->RestoreMatrix(var); kenv->ExecStack.Pop(); if(flags&2) kenv->ExecStack.PushMul(mat1); else { kenv->ExecStack.Push(mat1); kenv->ExecStack.Top().l.Add3(matrix.l); } kenv->SetMatrix(mat0,var); ExecSceneInput(op,kenv,1); //op->ExecInput(kenv,1); kenv->RestoreMatrix(var); kenv->ExecStack.Pop(); } } /****************************************************************************/ GenScene * __stdcall Init_Scene_Walk(GenScene *scene0, sU32 Flags,sInt FootCount,sF32 StepTresh,sF32 RunLowTresh,sF32 RunHighTresh, sInt2 ft,sF322 sl,sF322 ss,sF322 sn, sF323 l0,sF323 l1,sF323 l2,sF323 l3,sF323 l4,sF323 l5,sF323 l6,sF323 l7, sF32 scanup,sF32 scandown, KSpline *stepspline) { GenScene *scene; GenScene *add; sREGZONE(ExecWalk); scene = new GenScene(); add = MakeScene(scene0); if(add) *scene->Childs.Add() = add; return scene; } #pragma lekktor(off) struct WalkMem : public KInstanceMem { // KKriegerParticle FootPart[8]; // KKriegerParticle BodyPart; sVector FootOld[8]; sVector FootNew[8]; sInt StepTime[8]; sInt LastTime; sVector OldPos,NewPos,FootCenter; sInt State; // state 0=walk, 1=run sInt LastLeg; // 0 = left; 1 = right sInt NextLeg; // (LastLeg+1)%FootGroup sInt Idle; // no new steps issued last frame sVector Deviation; // avoid walls sInt DeviationFlag; sInt InitSteps; sVector FootDelta[8]; // position of the foot-contact point relative to body } *mem; void __stdcall Exec_Scene_Walk(KOp *op,KEnvironment *kenv, sU32 Flags,sInt FootCount,sF32 StepTresh,sF32 RunLowTresh,sF32 RunHighTresh, sInt2 fg,sF322 sl,sF322 ss,sF322 sn, sF323 l0,sF323 l1,sF323 l2,sF323 l3,sF323 l4,sF323 l5,sF323 l6,sF323 l7, sF32 scanup,sF32 scandown, KSpline *stepspline) { sMatrix mat;//,save; // local vars sMatrix dir; // desired orientation of walker sVector savevar[8],savetime; sVector v,sum,foot[8],spline[8],stepdir; // sVector plane; sInt i,j; sInt bestleg; sInt time; sF32 dist,f,t; sInt changestate; // KKriegerCellAdd *cell; sZONE(ExecWalk); // copy of instance-vars sInt State; sInt LastLeg; sInt NextLeg; // parameters sInt FootGroup[2]; // groups of feet. sF32 StepLength[2]; // max. length of a step sInt StepSpeed[2]; // duration of a step in ms. sInt StepNext[2]; // when to start the next step in ms. steps may overlap // init parameters FootGroup[0] = fg.x; FootGroup[1] = fg.y; StepLength[0] = sl.x; StepLength[1] = sl.y; StepSpeed[0] = sFtol(ss.x*1000); StepSpeed[1] = sFtol(ss.y*1000); StepNext[0] = sMin(sFtol(sn.x*1000),StepSpeed[0]); StepNext[1] = sMin(sFtol(sn.y*1000),StepSpeed[1]); // init instance storage sMatrix &matrix = kenv->ExecStack.Top(); mem = kenv->GetInst(op); if(mem->Reset || (Flags&0x100) || kenv->TimeReset) { // cell = 0; // if(Flags&2) // cell = kenv->Game->FindCell(matrix.l); sum.Init(); mem->FootCenter.Init(); mem->InitSteps = FootCount*2; for(i=0;iFootDelta[i].Init((&l0)[i].x,(&l0)[i].y,(&l0)[i].z,0); v.Add3(matrix.l,mem->FootDelta[i]); v.w = 0; mem->FootOld[i] = mem->FootNew[i] = v; mem->StepTime[i] = StepSpeed[0]; // mem->FootPart[i].Init(v,sum,cell); mem->FootCenter.x += mem->FootDelta[i].x/FootCount; mem->FootCenter.z += mem->FootDelta[i].z/FootCount; } // mem->FootPart[FootCount-1].EndMarker = 1; // mem->BodyPart.Init(matrix.l,sum,cell); // mem->BodyPart.EndMarker = 1; mem->LastTime = kenv->CurrentTime; mem->NewPos = matrix.l; mem->State = 0; mem->LastLeg = 0; for(i=0;iFootDelta[i].Sub3(mem->FootCenter); } State = mem->State; LastLeg = mem->LastLeg; NextLeg = mem->NextLeg; // fake for animation #if !sINTRO if(Flags & 0x30) { sInt k; State = ((Flags&0x30)==0x20); j = FootGroup[State]; f = (StepTresh+RunLowTresh)/2; if(j) f = (RunLowTresh+RunHighTresh)/2; f = f/j; if(Flags&0x40) f *= 2; time = kenv->CurrentTime % (StepNext[State]*j); k = kenv->CurrentTime / (StepNext[State]*j); for(i=0;iStepTime[i] = time - (StepNext[State]*(i%j)); if(Flags&0x80) mem->FootOld[i].Init(0,0,f*(i%j-(time*1.0f/StepNext[State])-(j-1)*0.5f)); else mem->FootOld[i].Init(0,0,f*(k*j+(i%j))); mem->FootOld[i].Add3(mem->FootDelta[i]); mem->FootNew[i] = mem->FootOld[i]; mem->FootNew[i].z += f*j; if(mem->StepTime[i]StepTime[i] += StepNext[State]*j; mem->FootOld[i].z -= f*j; mem->FootNew[i].z -= f*j; } if(mem->StepTime[i]<0) { mem->FootNew[i] = mem->FootOld[i]; mem->StepTime[i] = StepSpeed[State]; } if(mem->StepTime[i]>StepSpeed[State]) mem->StepTime[i] = StepSpeed[State]; } } #endif // animate sum.Init(); f = 0; for(i=0;iStepTime[i]/StepSpeed[State],1.0f,0.0f); if(iEval((t+State)*0.5f,spline[i]); if(mem->FootDelta[i].x<0) spline[i].x=-spline[i].x; if(mem->FootDelta[i].z<0) spline[i].z=-spline[i].z; spline[i].w = spline[i].w-State; } else { spline[i].x = 0; spline[i].y = sFSin(t*sPI)*0.25f; spline[i].z = 0; spline[i].w = t; } #pragma lekktor(off) foot[i].Lin3(mem->FootOld[i],mem->FootNew[i],spline[i].w); foot[i].w = 1.0f; /* if(Flags&0x02) { foot[i].y += spline[i].y; mem->FootPart[i].Control(foot[i]); foot[i].y -= spline[i].y; } */ sum.Add3(foot[i]); } sum.Scale3(1.0f/FootCount); mat.i.Init(0,0,0,0); mat.j.Init(0,0,0,0); // ryg 040820 mat.k.Init(0,0,0,0); mat.l.Init(sum.x,sum.y,sum.z,1); for(i=0;iFootDelta[i].x); mat.j.AddScale3(v,mem->FootDelta[i].y); mat.k.AddScale3(v,mem->FootDelta[i].z); } #pragma lekktor(on) switch((Flags>>2)&3) { case 0: // straight, copy from input mat.i = matrix.i; mat.j = matrix.j; mat.k = matrix.k; break; case 2: // use xy mat.i.Unit3(); mat.j.Init(0,1,0,0); mat.k.Cross4(mat.i,mat.j); mat.k.Unit3(); mat.j.Cross4(mat.k,mat.i); mat.j.Unit3(); break; case 1: // use y mat.k = matrix.k; case 3: // use xz mat.k.Unit3(); mat.j.Cross4(mat.k,mat.i); mat.j.Unit3(); mat.i.Cross4(mat.j,mat.k); mat.i.Unit3(); break; } #pragma lekktor(off) t = (f+LastLeg)/FootGroup[State]; if(t>=2.0f) t-=2.0f; if(t>=1.0f) t-=1.0f; t = (t+State)*0.5f; savetime = kenv->Var[KV_LEG_TIMES]; kenv->Var[KV_LEG_TIMES].Init(t,0,0,0); // advance time = kenv->CurrentTime-mem->LastTime; mem->LastTime = kenv->CurrentTime; if(time<0) time = 0; dir = matrix; if(mem->DeviationFlag>0) { dir.l.Add3(mat.l,mem->Deviation); } /* if(mem->BodyPart.Cell) { dir.l.y += 0.5f; if(kenv->CurrentEvent && kenv->CurrentEvent->Monster) mem->BodyPart.SkipCell = &kenv->CurrentEvent->Monster->Cell; mem->BodyPart.Control(dir.l); dir.l.y -= 0.5f; } */ dir.k.y = 0; dir.k.Unit3(); dir.j.Init(0,1,0,0); dir.i.Cross4(dir.j,dir.k); for(i=0;iStepTime[i]StepTime[i] += time; } // find distance dist = 0; stepdir.Init(); NextLeg = (LastLeg+1)%FootGroup[State]; bestleg = NextLeg; for(i=0;iFootDelta[i]); v.Sub3(foot[i]); v.y = 0; f = v.Abs3(); if(f>dist && mem->StepTime[i]>=StepSpeed[State]) { dist = f; stepdir = v; bestleg = i; } savevar[i] = kenv->Var[KV_LEG_L0+i]; v.Rotate3(dir,spline[i]); kenv->Var[KV_LEG_L0+i].Add3(foot[i],v); kenv->Var[KV_LEG_L0+i].w = spline[i].w; } // change walking/running changestate = 1; for(i=0;iStepTime[i]RunHighTresh) || (State==1 && dist in animation -> // changestate = 1 -> animation done. -> issue bestleg when idle // changestate = 2 -> in animation, change state -> don't issue new steps // changestate = 3 -> animation done, change state -> change state really // sDPrintF("%08x:state %d change %d dist %f | %4d %4d %4d %4d %4d %4d\n",mem,State,changestate,dist,mem->StepTime[0],mem->StepTime[1],mem->StepTime[2],mem->StepTime[3],mem->StepTime[4],mem->StepTime[5]); if(changestate==3) { if((State==0 && dist>RunHighTresh) || (State==1 && distStepTime[i]=StepSpeed[State]; NextLeg = bestleg%FootGroup[State]; } } bestleg = bestleg%FootGroup[State]; if(mem->Idle && changestate==1) NextLeg = bestleg; // do the next step mem->Idle = 0; if(changestate!=2 && mem->StepTime[LastLeg]>=StepNext[State] && mem->StepTime[NextLeg]>=StepSpeed[State]) { if(mem->InitSteps>0) { mem->InitSteps--; dist = 1024; } if(mem->DeviationFlag>0) mem->DeviationFlag--; if(dist>StepTresh) { v.Sub3(dir.l,mat.l); f = v.Abs3(); if((Flags & 1) && mem->InitSteps==0) NextLeg = bestleg; if(f>StepLength[State]) { mem->NewPos = mat.l; mem->NewPos.AddScale3(v,StepLength[State]/f); } else { mem->NewPos = dir.l; } // mem->NewPos.y = 0; dir.l = mem->NewPos; j = mem->StepTime[LastLeg]-StepNext[State]; for(i=NextLeg;iFootOld[i] = foot[i];//mem->FootNew[i]; // sDPrintF("soll: %06.3f %06.3f %06.3f --\n ist: %06.3f %06.3f %06.3f\n",mem->FootOld[i].x,mem->FootOld[i].y,mem->FootOld[i].z,dir.l.x,dir.l.y,dir.l.z); v = mem->FootDelta[i]; v.y = 0; v.Rotate34(dir); /* if(mem->FootPart[i].Cell) { KKriegerCellAdd *cell; sVector p0,p1; mem->FootNew[i] = v; // do the step in any case... mem->StepTime[i] = j; kenv->Game->CollisionForMonsterMode = 1; // and then find a better point-- p0 = v; p0.y += scanup; cell = kenv->Game->FindCell(p0); if(cell) { p1 = v; p1.y -= scandown; if(kenv->Game->FindFirstIntersect(p0,p1,cell,&plane)) { if(plane.y>0.75 && p1.yFootNew[i] = p1; mem->StepTime[i] = j; } } } kenv->Game->CollisionForMonsterMode = 0; } else*/ { mem->FootNew[i] = v; mem->StepTime[i] = j; } } LastLeg = NextLeg; } else { mem->Idle = 1; } } // paint & cleanup /* if(mem->BodyPart.Cell) { // kenv->Game->AddPart(&mem->FootPart[0]); kenv->Game->AddPart(&mem->BodyPart); } */ kenv->ExecStack.Push(mat); //save = kenv->ExecMatrix; //kenv->ExecMatrix = mat; op->ExecInputs(kenv); kenv->ExecStack.Pop(); //kenv->ExecMatrix = save; mem->State = State; mem->LastLeg = LastLeg; mem->NextLeg = NextLeg; for(i=0;iVar[KV_LEG_L0+i] = savevar[i]; } kenv->Var[KV_LEG_TIMES] = savetime; // if(kenv->CurrentEvent) // kenv->CurrentEvent->ReturnMatrix = mat; } #pragma lekktor(on) /****************************************************************************/ GenScene * __stdcall Init_Scene_Rotate(GenScene *scene0,sF323 dir,sInt axxis) { GenScene *scene; GenScene *add; scene = new GenScene(); add = MakeScene(scene0); if(add) *scene->Childs.Add() = add; return scene; } void __stdcall Exec_Scene_Rotate(KOp *op,KEnvironment *kenv,sF323 dir,sInt axxis) { sMatrix mat;//,save; sVector v; v.Init(dir.x,dir.y,dir.z,0); v.UnitSafe3(); const sMatrix &matrix = kenv->ExecStack.Top(); //save = kenv->ExecMatrix; switch(axxis) { case 0: mat.i = v; mat.k.Cross4(mat.i,matrix.j); mat.k.Unit3(); mat.j.Cross4(mat.k,mat.i); mat.j.Unit3(); break; case 1: mat.j = v; mat.i.Cross4(mat.j,matrix.k); mat.i.Unit3(); mat.k.Cross4(mat.i,mat.j); mat.k.Unit3(); break; case 2: mat.k = v; mat.j.Cross4(mat.k,matrix.i); mat.j.Unit3(); mat.i.Cross4(mat.j,mat.k); mat.i.Unit3(); break; default: mat = kenv->CurrentCam.CameraSpace; break; } mat.l = matrix.l; kenv->ExecStack.Push(mat); op->ExecInputs(kenv); kenv->ExecStack.Pop(); } /****************************************************************************/ GenScene * __stdcall Init_Scene_Forward(GenScene *scene0,sF32 tresh) { GenScene *scene; GenScene *add; scene = new GenScene(); add = MakeScene(scene0); if(add) *scene->Childs.Add() = add; return scene; } struct ForwardMem : KInstanceMem { sVector oldpos; }; void __stdcall Exec_Scene_Forward(KOp *op,KEnvironment *kenv,sF32 tresh) { sMatrix mat;//,save; sVector v; sF32 f; ForwardMem *mem; //save = kenv->ExecMatrix; const sMatrix &matrix = kenv->ExecStack.Top(); mem = kenv->GetInst(op); #pragma lekktor(off) if(mem->Reset) { mem->oldpos = matrix.l; mem->oldpos.AddScale3(matrix.k,-tresh); } #pragma lekktor(on) v.Sub3(matrix.l,mem->oldpos); f = v.UnitAbs3(); mem->oldpos = matrix.l; mem->oldpos.AddScale3(v,-tresh); mat.j.Init(0,1,0,0); mat.k = v; mat.k.w = 0; mat.i.Cross4(mat.j,mat.k); mat.j.Cross4(mat.k,mat.i); mat.l = matrix.l; kenv->ExecStack.Push(mat); //kenv->ExecMatrix = mat; op->ExecInputs(kenv); kenv->ExecStack.Pop(); //kenv->ExecMatrix = save; } /****************************************************************************/ #if sLINK_KKRIEGER GenScene * __stdcall Init_Scene_Physic(GenScene *scene0,sInt flags,sF323 speed,sF323 scale,sF323 rmassf,sF32 mass,sInt partkind) { GenScene *scene; GenScene *add; scene = new GenScene(); if(scene0) { add = MakeScene(scene0); if(add) *scene->Childs.Add() = add; } return scene; } struct PhysicMem : KInstanceMem { sInt Flags; KKriegerCellDynamic Cell; // KKriegerParticle Part; // KKriegerPartBox Box; }; void __stdcall Exec_Scene_Physic(KOp *op,KEnvironment *kenv,sInt flags,sF323 speedf,sF323 scalef,sF323 rmassf,sF32 mass,sInt partkind) { sMatrix mat;//,save; PhysicMem *mem; sVector speed; sVector scale; KEvent *monsterevent; sMatrix m1; // sInt i; KKriegerCellDynamic *monstercell; speed.Init(speedf.x,speedf.y,speedf.z); scale.Init(scalef.x,scalef.y,scalef.z); monsterevent = 0; monstercell =0 ; if(flags & 0x20) { monsterevent = kenv->CurrentEvent; if(monsterevent && monsterevent->Monster==0) monstercell = &kenv->Game->Player.HitCell; } //save = kenv->ExecMatrix; //mat = save; mat = kenv->ExecStack.Top(); speed.Rotate3(mat); mem = kenv->GetInst(op); m1.Init(); #pragma lekktor(off) if(mem->Reset) { #pragma lekktor(on) mem->Flags = flags; switch(flags&3) { case 0: default: /* mem->Part.Init(mat.l,speed,kenv->Game->PlayerCell); mem->Part.EndMarker = 1; mem->Part.Mass = mass; mem->Part.Kind = partkind; mem->Part.ShotEvent = monsterevent; mem->Part.SkipCell = monstercell; */ break; case 1: /* mem->Box.Init(mat,scale,speed,kenv->Game->PlayerCell); for(i=0;i<8;i++) { mem->Box.Part[i].Mass = mass; mem->Box.Part[i].Kind = partkind; mem->Box.Part[i].ShotEvent = monsterevent; mem->Box.Part[i].SkipCell = monstercell; } */ break; case 2: mem->Cell.Init(m1,scale,KCM_SUB); mem->Cell.PrepareDynamic(mat); break; case 3: /* mem->Cell.Init(m1,scale,KCM_SUB); mem->Cell.PrepareDynamic(mat); mem->Box.Init(mat,scale,speed,kenv->Game->PlayerCell); for(i=0;i<8;i++) { mem->Box.Part[i].SkipCell = &mem->Cell; mem->Box.Part[i].Kind = partkind; mem->Box.Part[i].ShotEvent = monsterevent; } mem->Cell.PartBox = &mem->Box; */ break; } } if(flags & 0x10) mem->Cell.Monster = kenv->EventMonster; switch(mem->Flags&3) { case 0: default: /* kenv->Game->AddPart(&mem->Part); mat.l = mem->Part.Pos; mat.l.w = 1.0f; */ break; case 1: /* mem->Box.GetMatrix(mat); mem->Box.Register(kenv->Game); */ break; case 2: mem->Cell.Matrix1 = mat; kenv->Game->AddDCell(&mem->Cell); break; case 3: /* mat = mem->Cell.ConfirmedMatrix; // mem->Box.GetMatrix(mat); // mem->Cell.Matrix1 = mat; mem->Box.Register(kenv->Game); kenv->Game->AddDCell(&mem->Cell); */ break; } kenv->ExecStack.Push(mat); op->ExecInputs(kenv); kenv->ExecStack.Pop(); // if(op->GetInput(0)) // op->GetInput(0)->Exec(kenv); } #endif /****************************************************************************/ GenScene * __stdcall Init_Scene_ForceLights(GenScene *in,sInt mode,sInt sw) { return in; } void __stdcall Exec_Scene_ForceLights(KOp *op,KEnvironment *kenv,sInt mode,sInt sw) { sInt inc; inc = (!mode || (kenv->Game && kenv->Game->Switches[sw])) ? 1 : 0; //kenv->ForceLights += inc; op->ExecInputs(kenv); //kenv->ForceLights -= inc; } /****************************************************************************/ GenScene * __stdcall Init_Scene_MatHack(GenMaterial *mtrl) { if(mtrl) mtrl->Release(); return new GenScene; } void __stdcall Exec_Scene_MatHack(KOp *op,KEnvironment *kenv) { op->ExecInputs(kenv); } /****************************************************************************/ GenScene * __stdcall Init_Scene_Sector(GenScene *scene0) { GenScene *scene,*add; scene = new GenScene; add = MakeScene(scene0); if(add) *scene->Childs.Add() = add; scene->IsSector = sTRUE; return scene; } void __stdcall Exec_Scene_Sector(KOp *op,KEnvironment *kenv) { GenScene *scene; scene = (GenScene *)op->Cache; sVERIFY(scene && scene->ClassId == KC_SCENE); if(op->GetInput(0)) Engine->AddSectorJob(scene,op->GetInput(0),kenv->ExecStack.Top()); /*{ sVERIFY(!kenv->CurrentSector); scene->Next = kenv->ExecSectorList; scene->Sector = op->GetInput(0); scene->SectorMatrix = kenv->ExecStack.Top(); scene->SectorPaintThisFrame = sFALSE; kenv->ExecSectorList = scene; }*/ } /****************************************************************************/ GenScene * __stdcall Init_Scene_Portal(GenScene *in,GenScene *s0,GenScene *s1,GenScene *si,sF322 x,sF322 y,sF322 z,sInt cost,sF32 door) { if(s0) s0->Release(); if(s1) s1->Release(); if(si) si->Release(); return in ? in : new GenScene; } void __stdcall Exec_Scene_Portal(KOp *op,KEnvironment *kenv,sF322 x,sF322 y,sF322 z,sInt cost,sF32 door) { //KPortalJob *job; KOp *s[3]; GenScene *sectors[3]; s[0] = op->GetLink(0); s[1] = op->GetLink(1); s[2] = op->GetLink(2); if(s[2] && !s[2]->CheckOutput(KC_SCENE)) s[2] = 0; if(s[0] && s[1] && s[0]->CheckOutput(KC_SCENE) && s[1]->CheckOutput(KC_SCENE)) { for(sInt i=0;i<3;i++) sectors[i] = (s[i] && s[i]->Cache) ? (GenScene *)s[i]->Cache : 0; sAABox box; box.Min.Init(x.x,y.x,z.x,1.0f); box.Max.Init(x.y,y.y,z.y,1.0f); Engine->AddPortalJob(sectors,box,kenv->ExecStack.Top(),(door >= 0.02f) ? cost : 256); #if !sPLAYER && 0 // FIXME! if(ShowPortalOp == op) ShowPortalJob = job; #endif } #if !sPLAYER // FIXME! if(ShowPortalOp == op) { for(sInt i=0;i<8;i++) { sVector p; p.Init((i&1) ? x.y : x.x,(i&2) ? y.y : y.x,(i&4) ? z.y : z.x,1); ShowPortalCube[i].Rotate34(kenv->ExecStack.Top(),p); } ShowPortalOpProcessed = sTRUE; } #endif op->ExecInput(kenv,0); } /****************************************************************************/ GenScene * __stdcall Init_Scene_AdjustPass(GenScene *in,sInt adjust) { return in; } void __stdcall Exec_Scene_AdjustPass(KOp *op,KEnvironment *kenv,sInt adjustPass) { RenderPassAdjust += adjustPass; op->ExecInput(kenv,0); RenderPassAdjust -= adjustPass; } /****************************************************************************/ struct ScenePartMem : public KInstanceMem { sInt Count; sInt OldCount; sInt Seed; sInt Mode; sF323 Rand; sF323 RandRot; sF323 RandSpeed; sF32 RandForw; sF323 RandRotSpeed; sF32 ComeOut; sVector *Pos; sVector *Speed; sVector *Rot; sVector *RotSpeed; }; GenScene * __stdcall Init_Scene_Particles(GenScene *scene0,GenSpline *gspline, sInt mode,sInt count,sInt seed, sF323 rand,sF323 rot,sF323 rotspeed,sF32 anim, sF323 line,sF323 randspeed,sF323 gravity, sF32 forwspeed,sF32 comeout,sF323 randrotspeed,sF323 pulse,KSpline *spline) { GenScene *scene; GenScene *add; scene = new GenScene(); add = MakeScene(scene0); if(add) *scene->Childs.Add() = add; if(gspline) gspline->Release(); sREGZONE(InstanceMat); return scene; } /****************************************************************************/ void __stdcall Exec_Scene_Particles(KOp *op,KEnvironment *kenv, sInt mode,sInt count,sInt seed, sF323 rand,sF323 rot,sF323 rotspeed,sF32 anim, sF323 line,sF323 randspeed,sF323 gravity, sF32 forwspeed,sF32 comeout,sF323 randrotspeed,sF323 pulse,KSpline *spline) { sInt i; sMatrix mat,mat0,mat1; ScenePartMem *mem; sF32 f; sVector v,v0; GenSpline *gsp; gsp = 0; if(op->GetInputCount()>=2) gsp = (GenSpline *)op->GetInput(1)->Cache; //spline = op->GetSpline(0); mem = kenv->GetInst(op); if(mem->Reset || mem->Mode!=mode || mem->Count!=count || mem->Seed!=seed || mem->Rand.x!=rand.x || mem->Rand.y!=rand.y || mem->Rand.z!=rand.z || mem->RandRot.x!=rot.x || mem->RandRot.y!=rot.y || mem->RandRot.z!=rot.z || mem->RandForw!=forwspeed || mem->ComeOut != comeout || mem->RandRotSpeed.x!=randrotspeed.x || mem->RandRotSpeed.y!=randrotspeed.y || mem->RandRotSpeed.z!=randrotspeed.z ) { if(!mem->Reset) delete[] mem->Pos; mem->Count = count; mem->Mode = mode; mem->Seed = seed; mem->Rand = rand; mem->RandRot = rot; mem->RandSpeed = randspeed; mem->RandForw = forwspeed; mem->RandRotSpeed = randrotspeed; mem->ComeOut = comeout; if(mode&0x10) { mem->Pos = new sVector[count*4]; mem->Speed = mem->Pos+count; mem->Rot = mem->Pos+count*2; mem->RotSpeed = mem->Pos+count*3; } else { mem->Pos = new sVector[count*2]; mem->Speed = mem->Pos+count; mem->Rot = 0; mem->RotSpeed = 0; } mem->DeleteArray = mem->Pos; sSetRndSeed(seed); for(i=0;iPos[i].x = (sFGetRnd(2.0f)-1.0f); mem->Pos[i].y = (sFGetRnd(2.0f)-1.0f); mem->Pos[i].z = (sFGetRnd(2.0f)-1.0f); if((mode&12)==4) mem->Pos[i].Unit3(); } while(((mode&12)==8) && mem->Pos[i].Dot3(mem->Pos[i])>1.0); if(mode&0x20) mem->Pos[i].w = 1.0f*i/count; else mem->Pos[i].w = sFGetRnd(1-comeout)+comeout; mem->Pos[i].x *= rand.x*0.5f; mem->Pos[i].y *= rand.y*0.5f; mem->Pos[i].z *= rand.z*0.5f; do { mem->Speed[i].x = (sFGetRnd(2.0f)-1.0f); mem->Speed[i].y = (sFGetRnd(2.0f)-1.0f); mem->Speed[i].z = (sFGetRnd(2.0f)-1.0f); } while(mem->Speed[i].Dot3(mem->Speed[i])>1.0); mem->Speed[i].w = sFGetRnd(1.0f); if(mem->Rot) { mem->Rot[i].x = sFGetRnd(rot.x); mem->Rot[i].y = sFGetRnd(rot.y); mem->Rot[i].z = sFGetRnd(rot.z); } if(mem->RotSpeed) { mem->RotSpeed[i].x = sFGetRnd(randrotspeed.x); mem->RotSpeed[i].y = sFGetRnd(randrotspeed.y); mem->RotSpeed[i].z = sFGetRnd(randrotspeed.z); } } } if(!(mode&0x80)) anim = sFMod(anim,1.0f); if(anim<0) anim+=1; EngMesh *engmesh = 0; GenScene *myCache = (GenScene *) op->Cache; sMatrix *minmeshmat = 0,*origmat = 0; if((mode&0x100) && myCache && myCache->Childs.Count) { engmesh = myCache->Childs[0]->DrawMesh; if(engmesh) minmeshmat = origmat = engmesh->GetInstanceMatrices(mem->Count); } sVector save0,save1; save0 = kenv->Var[KV_SELECT]; save1 = kenv->Var[KV_FRACTION]; sZONE(InstanceMat); for(i=0;iCount;i++) { f = anim + mem->Pos[i].w + mem->RandForw*mem->Speed[i].w*anim; if(f<1.0f && (mode&64)) continue; while(f>=1.0f) f -= 1.0f; mat.Init(); sF32 g = (f*f); sVector vpos; vpos.x = mem->Pos[i].x + mem->Speed[i].x*f*randspeed.x+g*gravity.x; vpos.y = mem->Pos[i].y + mem->Speed[i].y*f*randspeed.x+g*gravity.y; vpos.z = mem->Pos[i].z + mem->Speed[i].z*f*randspeed.x+g*gravity.z; if(pulse.z!=0) vpos.Scale3(sFSin(anim*sPI2F*pulse.x + f*sPI2F*pulse.y)*pulse.z+1); if((mode&1) && spline) // spline mode { spline->Eval(f,v); if(mode&0x10) { spline->Eval(f+0.01f,v0); v0.Sub3(v); mat.InitDir(v0); } mat.l.x += vpos.x + v.x; mat.l.y += vpos.y + v.y; mat.l.z += vpos.z + v.z; mat.l.w = 1; } if(gsp) // genspline mode { sVector vp; sF32 zoom; gsp->Eval(f,0,mat,zoom); vp.x = vpos.x; vp.y = vpos.y; vp.z = vpos.z; vp.w = 0; vp.Rotate3(mat); mat.l.Add3(vp); } else // line mode { mat.l.x += vpos.x + line.x*f; mat.l.y += vpos.y + line.y*f; mat.l.z += vpos.z + line.z*f; mat.l.w = 1; } if(mem->Rot||mem->RotSpeed) { sF32 rx,ry,rz; rx = f*rotspeed.x; ry = f*rotspeed.y; rz = f*rotspeed.z; if(mem->Rot) { rx += mem->Rot[i].x; ry += mem->Rot[i].y; rz += mem->Rot[i].z; } if(mem->RotSpeed) { rx += mem->RotSpeed[i].x*f; ry += mem->RotSpeed[i].y*f; rz += mem->RotSpeed[i].z*f; } mat0.InitEuler(rx,ry,rz); // mem->Rot[i].x+f*rotspeed.x*rrs, // mem->Rot[i].y+f*rotspeed.y*rrs, // mem->Rot[i].z+f*rotspeed.z*rrs); mat1.MulA(mat0,mat); mat = mat1; } if(minmeshmat) { *minmeshmat++ = mat; } else { kenv->Var[KV_SELECT].Init(i,i,i,i); kenv->Var[KV_FRACTION].Init(f,f,f,f); kenv->ExecStack.PushMul(mat); ExecSceneInputs(op,kenv,0); kenv->ExecStack.Pop(); } } if(engmesh) engmesh->UpdateInstanceCount(minmeshmat - origmat); kenv->Var[KV_SELECT] = save0; kenv->Var[KV_FRACTION] = save1; if(engmesh) Engine->AddPaintJob(engmesh,kenv->ExecStack.Top(),0,0); } /****************************************************************************/ GenScene * __stdcall Init_Scene_ApplySpline(GenScene *add,GenSpline *sp) { GenScene *scene; sp->Release(); add = MakeScene(add); if(!add) return 0; scene = new GenScene; *scene->Childs.Add() = add; return scene; } void __stdcall Exec_Scene_ApplySpline(KOp *op,KEnvironment *kenv,sF32 time) { sMatrix mat; GenSpline *sp; sF32 zoom; sp = (GenSpline *)op->GetInput(1)->Cache; sVERIFY(sp); sp->Eval(time,0,mat,zoom); kenv->ExecStack.PushMul(mat); ExecSceneInputs(op,kenv,0); kenv->ExecStack.Pop(); } /****************************************************************************/ GenScene * __stdcall Init_Scene_Marker(GenScene *add,sInt marker) { GenScene *scene = new GenScene; *scene->Childs.Add() = MakeScene(add); return scene; } void __stdcall Exec_Scene_Marker(KOp *op,KEnvironment *kenv,sInt marker) { sVERIFY(marker>=0 && markerMarkers)); kenv->Markers[marker] = kenv->ExecStack.Top(); ExecSceneInputs(op,kenv,0); } /****************************************************************************/ GenScene * __stdcall Init_Scene_LOD(GenScene *high,GenScene *low,sF32 lod) { GenScene *scene = new GenScene; *scene->Childs.Add() = MakeScene(high); if(low) *scene->Childs.Add() = MakeScene(low); return scene; } void __stdcall Exec_Scene_LOD(KOp *op,KEnvironment *kenv,sF32 lod) { sF32 dist; sVector v; sMatrix mat0; sMatrix mat1; mat0 = kenv->ExecStack.Top(); mat1 = kenv->CurrentCam.CameraSpace; v.Sub3(mat1.l,mat0.l); dist = -v.Dot3(mat1.k); if(distGetInputCount()==2) ExecSceneInput(op,kenv,1); } /****************************************************************************/ GenScene * __stdcall Init_Scene_Ambient(sU32 color) { return new GenScene; } void __stdcall Exec_Scene_Ambient(KOp *op,KEnvironment *kenv,sU32 color) { Engine->AddAmbientLight(color); } /****************************************************************************/