Trivial Solutions
                    The LoseThos 64-bit PC Operating System
File:/LT/Demo/Graphics/Camp.CPZ
This, and all LoseThos files, are public domain.  Do whatever you like.
God is watching; God is just; God is never out-done in generosity.  He talks!

LoseThos code compiles with the 64-bit LoseThos compiler/assembler I wrote.
Boot the LoseThos CD and you can compile it.  Not in Kansas anymore!

Click here for preliminary compiler information you need.

//This uses fixed-point.

#define CO_PERSON       1
#define CO_TENT 2

class CObj
{
  I64 x,y,z;
  I64 dx,dy,dz;
  I64 type;
};


#define MAX_PEOPLE      1024
#define TENT_RATIO      40
#define MAX_TENTS       (MAX_PEOPLE/TENT_RATIO+1)






  <1>/* Graphics Not Rendered in HTML */





  <2>/* Graphics Not Rendered in HTML */






  <3>/* Graphics Not Rendered in HTML */



U8 *people_img[4]={<2>,<1>,<3>,<1>};















            <4>/* Graphics Not Rendered in HTML */

U8 *tent_img=<4>;







<5>/* Graphics Not Rendered in HTML */





I64 num_objs;
CObj objs[MAX_PEOPLE+MAX_TENTS];
CObj camp_view_point;

#define CAMP_WIDTH      600
#define CAMP_SCALE      300
#define CAMP_Z_CLIP     10

U0 CTransform(GrBitMap *base,I64 *x,I64 *y,I64 *z)
{
  *x-=camp_view_point.x;
  *y-=camp_view_point.y;
  *z-=camp_view_point.z;

  GrRot(base->r,x,y,z);

  *x = *x *-CAMP_SCALE/ *z;
  *y = *y *-CAMP_SCALE/ *z;

  *x=base->x+*x;
  *y=base->y-*y;
  *z=base->z-*z;
}

I64 mp_done_flags;
I64 cx,cy,*r1; //could put these in a record and pass in
F64 frame;
I32 *depth_buf;
U0 MPDrawMeeting(TaskStruct *task)
{
  GrBitMap *base=GrAlias(gr_refreshed_base,task);
  F64 s;
  U8 *img,*img1,*img2;
  I64 i,x,y,z,*r2,*old_r=base->r,
     lo= Gs->num   *num_objs/mp_cnt,
     hi=(Gs->num+1)*num_objs/mp_cnt;
  base->flags|=BMF_TRANSFORMATION;
  base->depth_buf=depth_buf;
  base->x=cx;
  base->y=cy;
  base->z=0;
  base->transform=&GrTransform;
  for (i=lo;i<hi;i++) {
    GrSetRotMat(base,r1);
    base->x=cx;
    base->y=cy;
    base->z=0;
    x=objs[i].x.i32[1];
    y=objs[i].y.i32[1];
    z=objs[i].z.i32[1];
    CTransform(base,&x,&y,&z);
    if (z>CAMP_Z_CLIP) {
      s=0.5*ToF64(CAMP_SCALE)/z;
      if (objs[i].type==CO_PERSON) {
        img1=people_img[(i+ToI64(frame))&3];
        img2=people_img[(i+ToI64(frame)+1)&3];
        img=GrElemsInterpolate(img1,img2,frame%1.0);
      } else
        img=tent_img;

      r2=GrScaleMat(old_r,s);
      GrSetRotMat(base,r2);
      GrElemsPlot3b(base,x,y,z,img);
      Free(r2);
      if (objs[i].type==CO_PERSON)
        Free(img);
    }
  }
  base->r=old_r;
  base->depth_buf=NULL;
  GrDel(base);
  LBts(&mp_done_flags,Gs->num);
}

U0 DrawMeeting(TaskStruct *task)
{
  GrBitMap *base=GrAlias(gr_refreshed_base,task);
  static BoolI8 calf=FALSE,determined=FALSE;

//"tP" is a function holding time since boot, less pauses.
  I64 i,x,y,z,*r2,*old_r;
  F64 s;

  frame=4.0*Saw(tP(task),0.5);
  cx=task->win_pixel_width/2;
  cy=task->win_pixel_height/2;

  camp_view_point.x=0;
  camp_view_point.y=200-100*Sin(tP(task));
  camp_view_point.z=20+100*Cos(tP(task));

  GrAllocDepthBuf(base);
  depth_buf=base->depth_buf;
  base->flags|=BMF_TRANSFORMATION;
  r1=GrRotX(30.0*pi/180.0,task);
  old_r=base->r;

  base->pen_width=2;
  base->transform=&CTransform;
  base->x=cx;
  base->y=cy;
  base->z=0;
  GrSetRotMat(base,r1);

  x=0;y=0;z=-16*CAMP_WIDTH;
  base->transform(base,&x,&y,&z);
  base->color=LTCYAN;
  GrRect(base,0,0,task->win_pixel_width,y);

  base->color=BLACK;
  GrLine3(base,-32*CAMP_WIDTH,0,-16*CAMP_WIDTH,32*CAMP_WIDTH,0,-16*CAMP_WIDTH);

  GrLine3(base,-CAMP_WIDTH/2,0,0          ,CAMP_WIDTH/2,0,0);
  GrLine3(base,-CAMP_WIDTH/2,0,-CAMP_WIDTH,CAMP_WIDTH/2,0,-CAMP_WIDTH);
  GrLine3(base,-CAMP_WIDTH/2,0,0,-CAMP_WIDTH/2,0,-CAMP_WIDTH);
  GrLine3(base, CAMP_WIDTH/2,0,0, CAMP_WIDTH/2,0,-CAMP_WIDTH);

  base->transform=&GrTransform;

  if (tP(task)%10<5) {
    calf=FALSE;
    determined=FALSE;
  } else {
    if (!determined) {
      determined=TRUE;
      if (RandU16<MAX_U16/2)
        calf=TRUE;
    }
  }
 
  if (calf) {
    x=0;
    y=0;
    z=-CAMP_WIDTH/2;
    CTransform(base,&x,&y,&z);
    s=0.5*ToF64(CAMP_SCALE)/z;
    r2=GrScaleMat(old_r,s,task);
    GrSetRotMat(base,r2);
    GrElemsPlot3b(base,x,y,z,<5>);
    Free(r2);
  }

  mp_done_flags=0;
  for (i=1;i<mp_cnt;i++)
    MPJob(&MPDrawMeeting,task,1<<MPCf_FREE_ON_COMPLETE,1<<i);
  MPDrawMeeting(task);

  GrSetRotMat(base,old_r);
  if (calf && Blink(4.0,tP(task))) {
    base->color=YELLOW;
    GrPutS(base,cx-(15*FONT_WIDTH)/2,cy-3*FONT_HEIGHT,"!!Golden Calf!!");
  }
 
  while (mp_done_flags!=1<<mp_cnt-1)
    Yield;
  GrDel(base);
  Free(r1);
}

#define MAX_SPEED       2<<32

U0 AnimateTask(U64 dummy=0)
{
  nounusedwarn dummy;
  I64 i,x,z,dx,dz;
  F64 d;
  while (TRUE) {
    WinSync;
    for (i=0;i<num_objs;i++)
      if (objs[i].type==CO_PERSON) {
        if (tP(Fs->parent_task)%10<5) {
          objs[i].dx+=RandI32;
          objs[i].dz+=RandI32;
        } else { //Form circle
          x=CAMP_WIDTH/4*Cos((1.0+1.0/TENT_RATIO)*i*pi*2/num_objs);
          z=CAMP_WIDTH/4*Sin((1.0+1.0/TENT_RATIO)*i*pi*2/num_objs)-CAMP_WIDTH/2;
          dx=x-objs[i].x.i32[1];
          dz=z-objs[i].z.i32[1];
          d=Sqrt(SqrI64(dx)+SqrI64(dz));
          objs[i].dx=MAX_SPEED*(dx/d);
          objs[i].dz=MAX_SPEED*(dz/d);
        }
        objs[i].dx=LimitI64(objs[i].dx,-MAX_SPEED,MAX_SPEED);
        objs[i].dy=LimitI64(objs[i].dy,-MAX_SPEED,MAX_SPEED);
        objs[i].dz=LimitI64(objs[i].dz,-MAX_SPEED,MAX_SPEED);
        objs[i].x+=objs[i].dx;
        objs[i].y+=objs[i].dy;
        objs[i].z+=objs[i].dz;
        if (objs[i].x.i32[1]<-CAMP_WIDTH>>1) {
          objs[i].x=-CAMP_WIDTH>>1<<32;
          objs[i].dx=-objs[i].dx;
        }
        if (objs[i].x.i32[1]>CAMP_WIDTH>>1) {
          objs[i].x=CAMP_WIDTH>>1<<32;
          objs[i].dx=-objs[i].dx;
        }
        if (objs[i].z.i32[1]<-CAMP_WIDTH) {
          objs[i].z=-CAMP_WIDTH<<32;
          objs[i].dz=-objs[i].dz;
        }
        if (objs[i].z.i32[1]>0) {
          objs[i].z=0;
          objs[i].dz=-objs[i].dz;
        }
      }
    Sleep(20);
  }
}

U0 Camp(I64 num_people=100)
{
  I64 i,j=0,num_tents;

  if (num_people>MAX_PEOPLE)
    num_people=MAX_PEOPLE;

  MemSet(objs,0,sizeof(objs));
  for (i=0;i<num_people;i++) {
    objs[j].x=(RandU32%CAMP_WIDTH-CAMP_WIDTH>>1)<<32;
    objs[j].y=0;
    objs[j].z=-(RandU32%CAMP_WIDTH)<<32;
    objs[j].type=CO_PERSON;
    j++;
  }
  num_tents=(num_people+TENT_RATIO-1)/TENT_RATIO;
  for (i=0;i<num_tents;i++) {
    objs[j].x=(RandU32%CAMP_WIDTH-CAMP_WIDTH>>1)<<32;
    objs[j].y=0;
    objs[j].z=-(RandU32%CAMP_WIDTH)<<32;
    objs[j].type=CO_TENT;
    j++;
  }
  num_objs=j;

  LtfBottom; LtfClear;

  SettingsPush(Fs,TSF_SAME_SONG); //See SettingsPush
  try {
    WordStat(OFF);
    Fs->animate_task=Spawn(&AnimateTask,NULL,"Animate",Fs);
    Fs->update_win=&DrawMeeting;
    WinSync; //The old update clobbers text_attr
    Fs->text_attr=LTGREEN<<4+WHITE; //bk/fg

    GetChar;
  } catch
    CatchAll;
  SettingsPop(Fs,TSF_SAME_SONG);
}

//This is so I can use this file stand alone
//or as a component of a program.
#if IncludeDepth<2
Camp;
#endif
Historical capture: 2011-10-22. Home | Power on LoseThos | Sources and changes