Beispiel #1
0
unsigned RemoveOccludedObjects( Scene &scene, int width, int height )
{
  unsigned nOccluded = 0;

  HOM *head = BuildHOM( scene, width, height );

  size_t nObjs = scene.objects.size();
  std::vector< Box2D > projs( nObjs );
  for ( size_t i = 0; i < nObjs; ++i )
  {
    if ( !scene.objects[i].occluder )
    {
      // get bounding box from bounding volume
      std::vector< Point3D > projVerts( 8 );
      Object &obj  = scene.objects[i];
      Box3D &bound = obj.bound;

      projVerts[0] = GetScreenCrds( bound.origin, scene, width, height );
      projVerts[1] = GetScreenCrds( Point3D( bound.origin[0], bound.origin[1], bound.extent[2] ), scene, width, height );
      projVerts[2] = GetScreenCrds( Point3D( bound.origin[0], bound.extent[1], bound.extent[2] ), scene, width, height );
      projVerts[3] = GetScreenCrds( Point3D( bound.extent[0], bound.origin[1], bound.extent[2] ), scene, width, height );
      projVerts[4] = GetScreenCrds( Point3D( bound.extent[0], bound.extent[1], bound.origin[2] ), scene, width, height );
      projVerts[5] = GetScreenCrds( Point3D( bound.extent[0], bound.origin[1], bound.origin[2] ), scene, width, height );
      projVerts[6] = GetScreenCrds( Point3D( bound.origin[0], bound.extent[1], bound.origin[2] ), scene, width, height );
      projVerts[7] = GetScreenCrds( bound.extent, scene, width, height );

      projs[i].origin = force_cast<Point2D>( projVerts[0] );
      projs[i].extent = force_cast<Point2D>( projVerts[7] );
      float depth = projVerts[0][2];

      for ( size_t j = 0; j < 8; ++j )
      {
        // x bounds
        if ( projVerts[j][0] < projs[i].origin[0] )
          projs[i].origin[0] = projVerts[j][0];
        else if ( projVerts[j][0] > projs[i].extent[0] )
          projs[i].extent[0] = projVerts[j][0];
        // y bounds
        if ( projVerts[j][1] < projs[i].origin[1] )
          projs[i].origin[1] = projVerts[j][1];
        else if ( projVerts[j][1] > projs[i].extent[1] )
          projs[i].extent[1] = projVerts[j][1];
        // depth min
        if ( projVerts[j][2] < depth )
          depth = projVerts[j][2];
      }

      obj.occluded = Occluded( projs[i], depth, head, width, height );
      if ( obj.occluded )
        nOccluded++;
    }
  }

  delete head;

  return nOccluded;
}
Beispiel #2
0
static void DrawPart(int IsModel, struct L3PartS *PartPtr, int CurColor, float m[4][4])
{
	float          r[4], m1[4][4];
	int            i, Color;
	struct L3LineS *LinePtr;
	vector3d       v3d[4];

#ifdef USE_OPENGL
	float mm[4][4];
	float det = 0;

	if ((ldraw_commandline_opts.F & TYPE_F_STUDLINE_MODE) != 0)
	  if (PartPtr->IsStud)
	  {
	    DrawPartLine(PartPtr, CurColor, m);
	    //DrawPartBox(PartPtr, CurColor, m, 1);
	    return;
	  }

	// Draw only bounding boxes of top level parts if in fast spin mode.
	if (ldraw_commandline_opts.F & TYPE_F_BBOX_MODE) 
	  if (PartPtr->FromPARTS) // (!IsModel)
	  {
	    if (ldraw_commandline_opts.F & TYPE_F_NO_POLYGONS) 
	      DrawPartBox(PartPtr, CurColor, m, 1);
	    else
	      DrawPartBox(PartPtr, CurColor, m, 0);
	    return;
	  }	

	  if (PartPtr->IsStud)
	    det = M3Det(m); // Check the determinant of m to fix mirrored studs.
#endif

	for (LinePtr = PartPtr->FirstLine; LinePtr; LinePtr = LinePtr->NextLine)
	{
#ifdef USE_OPENGL
                char *s;

	        if (Skip1Line(IsModel,LinePtr))
		  continue;
#endif
		hardcolor = 0; // Assume color 16 or 24.
		switch (LinePtr->Color)
		{
		case 16:
			Color = CurColor;
			break;
		case 24:
#ifdef SIXTEEN_EDGE_COLORS
			if (0 <= CurColor  &&  CurColor <= 15)
				Color = edge_color(CurColor);
			else
				Color = 0;
#else
			Color = edge_color(CurColor);
#endif
			break;
		default:
			Color = LinePtr->Color;
#if 0
			if ((LinePtr->LineType == 3) || 
			    (LinePtr->LineType == 4))
			  // Hardcoded color = printed.  Blend me!
			  hardcolor = 1; 
#else
			if (LinePtr->LineType != 1)
			  // Hardcoded color = printed.  Blend me!
			  hardcolor = 1; 
#endif
			break;
		}
		switch (LinePtr->LineType)
		{
		case 0:
#ifdef USE_OPENGL
		        // Skip whitespace
		        for (s = LinePtr->Comment; *s != 0; s++)
		        {
			  if ((*s != ' ') && (*s != '\t'))
			    break;
			}
			if (strnicmp(s,"STEP",4) == 0)
			{
			  // if (include_stack_ptr <= ldraw_commandline_opts.output_depth )
			  {
			    zStep(stepcount,1);
			    stepcount++;
			  }
			}
			else if (strncmp(s,"CLEAR",5) == 0)
			{
			  // if (include_stack_ptr <= ldraw_commandline_opts.output_depth )
			  {
			    zClear();
			  }
			}
			// Experiment with MLCAD extensions
			// Based on info provided on lugnet.
			else if (strncmp(s,"BUFEXCHG A STORE",16) == 0)
			{
			  int k;

			  if (IsModel)
			  {
			    k = BufA1Store(IsModel,LinePtr);
			    printf("BUFEXCHG A STORE %d\n", k);
			  }
			}
			else if (strncmp(s,"BUFEXCHG A RETRIEVE",19) == 0)
			{
			  int j,n, opts, dcp, cp;
			  extern int curpiece;
			  extern int DrawToCurPiece;
			  void DrawModel(void);
			   
			  if (IsModel)
			  {
			    n = BufA1Retrieve(IsModel,LinePtr);
			    printf("BUFEXCHG A RETRIEVE %d\n", n);
			    // clear and redraw model up to saved point.
#if 0		    
			    opts = ldraw_commandline_opts.M;
			    ldraw_commandline_opts.M = 'C';
			    dcp = DrawToCurPiece;
			    DrawToCurPiece = 1;
			    cp = curpiece;
			    zClear();
			    curpiece = n;
			    Init1LineCounter();
			    BufA1Store(IsModel,LinePtr);
			    DrawModel();
			    //for(j = 0; j < n; j++)
			    //  Draw1Part(j, -1);
			    DrawToCurPiece = dcp;
			    curpiece = cp;
			    ldraw_commandline_opts.M = opts;
#endif
			  }
			}
			else if (strncmp(s,"GHOST",5) == 0)
			{
			  if (IsModel)
			  {
			    // Parse the rest of the line as a .DAT line.
			  }
			}
			if (ldraw_commandline_opts.M != 'C')
			{
			  // Non-continuous output stop after each step.
			}

			// Parse global color change meta-commands
			// Should?? be done by ReadMetaLine() in L3Input.cpp			
			// Should SAVE old colors, restore after the for loop.
			// To save space, build a linked list of saved colors.
			// Do NOT resave a color if its already saved.
			if ((strncmp(s,"COLOR",5) == 0) ||
			    (strncmp(s,"COLOUR",6) == 0))
			{
			  if (ldraw_commandline_opts.debug_level == 1)
			    printf("%s\n", s);
			  //0 COLOR 4 red 0 196 0 38 255 196 0 38 255
			  char colorstr[256];
			  char name[256];
			  int n, inverse_index;

			  n = sscanf(s, "%s %d %s %d %f %f %f %f %f %f %f %f",
				     colorstr, &i, name, &inverse_index,
				     &m1[0][0], &m1[0][1], &m1[0][2], &m1[0][3],
				     &m1[1][0], &m1[1][1], &m1[1][2], &m1[1][3]);
			  if (n != 12)
			  {
			    if (ldraw_commandline_opts.debug_level == 1)
			      printf("Illegal COLOR syntax %d\n",n);
			    break;
			  }
			  zcolor_modify(i,name,inverse_index,
					(int)m1[0][0], (int)m1[0][1], (int)m1[0][2], (int)m1[0][3],
					(int)m1[1][0], (int)m1[1][1], (int)m1[1][2], (int)m1[1][3]);
			}

			// Intercept the ldconfig.ldr !COLOUR meta command.
			if (ldlite_parse_colour_meta(s))
			  break;
#else
			if (strncmp(LinePtr->Comment,"STEP",4) == 0)
			{
				// STEP encountered, you may set some flags to enable/disable e.g. drawing
				// (Note that I have not tested this, but this is the way it is supposed to work :-)
			}
#endif
			break;
		case 1:
#ifdef USE_OPENGL
    // NOTE:  I could achieve L3Lab speeds if I delay rendering studs till last
    // then do occlusion tests on the bounding boxes before rendering.
    // Unfortunately GL_OCCLUSION_TEST_HP is an extension (SUN, HP, ???)
    // 
    // Other ideas include substituting GLU cylinder primitives for studs.  
		        if (LinePtr->PartPtr->IsStud)
			{
                          if ((ldraw_commandline_opts.F & TYPE_F_STUDLESS_MODE) != 0)
                            break;
#ifdef USE_OPENGL_OCCLUSION
                          if ((ldraw_commandline_opts.F & TYPE_F_STUDONLY_MODE) != 0)
			  {
			    M4M4Mul(m1,m,LinePtr->v);
			    if (Occluded(LinePtr->PartPtr, Color, m1))
			      break;
			  }
#endif
			}	    
#endif
			M4M4Mul(m1,m,LinePtr->v);
#ifdef USE_OPENGL
			// Negative determinant means its a mirrored stud.
			if (det < 0)
			{
			  // For now, we only support Paul Easters logo.dat texture.
			  // For display speed, we really should precalculate an IsLogo flag
			  // and use that here rather than IsStud.
			  if  (LinePtr->PartPtr && LinePtr->PartPtr->DatName &&
			       !stricmp(LinePtr->PartPtr->DatName, "logo.dat"))
			  {
			    float mirror[4][4] = {
			      {1.0,0.0,0.0,0.0},
			      {0.0,1.0,0.0,0.0},
			      {0.0,0.0,-1.0,0.0},
			      {0.0,0.0,0.0,1.0}
			    };
			    M4M4Mul(mm,m1,mirror);
			    memcpy(m1,mm,sizeof(m1));
			  }
			}
			  
			// implement nesting level counter.
			include_stack_ptr++;
			DrawPart(0,LinePtr->PartPtr,Color,m1);
			include_stack_ptr--;	
			// Do zStep() after the model, not toplevel parts.
#else
			DrawPart(0,LinePtr->PartPtr,Color,m1);
			if (IsModel) zStep(0,0);
#endif
			break;
		case 2:
#ifdef USE_OPENGL_OCCLUSION
		        if ((ldraw_commandline_opts.F & TYPE_F_STUDONLY_MODE) &&
			    !(PartPtr->IsStud))
                            break;
#endif
			for (i=0; i<LinePtr->LineType; i++)
			{
				M4V3Mul(r,m,LinePtr->v[i]);
				v3d[i].x=r[0];
				v3d[i].y=r[1];
				v3d[i].z=r[2];
			}
			render_line(&v3d[0],&v3d[1],Color);
			break;
		case 3:
#ifdef USE_OPENGL_OCCLUSION
		        if ((ldraw_commandline_opts.F & TYPE_F_STUDONLY_MODE) &&
			    !(PartPtr->IsStud))
                            break;
#endif
			for (i=0; i<LinePtr->LineType; i++)
			{
				M4V3Mul(r,m,LinePtr->v[i]);
				v3d[i].x=r[0];
				v3d[i].y=r[1];
				v3d[i].z=r[2];
			}
#ifdef USE_OPENGL
			// Try to render solid Primitives visibly when in XOR wire mode.
			if (ldraw_commandline_opts.F & TYPE_F_XOR_PRIMITIVE)
			{
			    render_line(&v3d[0],&v3d[1],Color);
			    render_line(&v3d[1],&v3d[2],Color);
			    render_line(&v3d[2],&v3d[0],Color);
			    break;
			}
#endif
			render_triangle(&v3d[0],&v3d[1],&v3d[2],Color);
			break;
		case 4:
#ifdef USE_OPENGL_OCCLUSION
		        if ((ldraw_commandline_opts.F & TYPE_F_STUDONLY_MODE) &&
			    !(PartPtr->IsStud))
                            break;
#endif
			for (i=0; i<LinePtr->LineType; i++)
			{
				M4V3Mul(r,m,LinePtr->v[i]);
				v3d[i].x=r[0];
				v3d[i].y=r[1];
				v3d[i].z=r[2];
			}
#ifdef USE_OPENGL
			// Try to render solid Primitives visibly when in XOR wire mode.
			if (ldraw_commandline_opts.F & TYPE_F_XOR_PRIMITIVE)
			{
			    render_line(&v3d[0],&v3d[1],Color);
			    render_line(&v3d[1],&v3d[2],Color);
			    render_line(&v3d[2],&v3d[3],Color);
			    render_line(&v3d[3],&v3d[0],Color);
			    break;
			}
#endif
			render_quad(&v3d[0],&v3d[1],&v3d[2],&v3d[3],Color);
			break;
		case 5:
#ifdef USE_OPENGL_OCCLUSION
		        if ((ldraw_commandline_opts.F & TYPE_F_STUDONLY_MODE) &&
			    !(PartPtr->IsStud))
                            break;
#endif
			for (i=0; i<4; i++)
			{
				M4V3Mul(r,m,LinePtr->v[i]);
				v3d[i].x=r[0];
				v3d[i].y=r[1];
				v3d[i].z=r[2];
			}
			render_five(&v3d[0],&v3d[1],&v3d[2],&v3d[3],Color);
			break;
		}
	}
	if (((zDetailLevel == TYPE_PART) && (PartPtr->FromPARTS)) ||
	    ((zDetailLevel == TYPE_P) && (PartPtr->FromP)))
	  zStep(-1, 0);
}
Beispiel #3
0
bool Occluded( const Box2D &bound, float depth, const HOM *hom, int scnWidth, int scnHeight, bool autoFind )
{
  // initiating case
  if ( autoFind )
  {
    // find best starting level
    float area    = bound.Area() * 100.f;
    float bestDif = (float)INFINITE;
    HOM *curLevel = const_cast<HOM *>( hom ); 
    while ( curLevel != NULL )
    {
      int pixArea  = ( ( scnWidth / curLevel->width ) * ( scnHeight / curLevel->height ) );
      float curDif = abs( (float)pixArea - area );
      if ( curDif < bestDif )
      {
        hom     = curLevel;
        bestDif = curDif;
      }
      curLevel = curLevel->prev;
    }
  }

  Box2D box;
  float denW = (float)( scnWidth  / hom->width  );
  float denH = (float)( scnHeight / hom->height );
  box.origin[0] = (float)bound.origin[0] / denW;
  box.extent[0] = (float)bound.extent[0] / denW;
  box.origin[1] = (float)bound.origin[1] / denH;
  box.extent[1] = (float)bound.extent[1] / denH;

  // test each pixel
  int nOpaques = 0;
  int yMin = std::max( (int)( box.origin[1] + .5f ), 0 );
  int yMax = std::min( (int)( box.extent[1] + .5f ), hom->height - 1 );
  int xMin = std::max( (int)( box.origin[0] + .5f ), 0 );
  int xMax = std::min( (int)( box.extent[0] + .5f ), hom->width  - 1 );
  for ( int y = yMin; y < yMax; ++y )
  {
    for ( int x = xMin; x < xMax; ++x )
    {
      float test = const_cast<HOM *>( hom )->Depth( x, y );
      if ( ( const_cast<HOM *>( hom )->Map( x, y ) < TRANSPARENCY_THRESHOLD ) ||
           ( depth < const_cast<HOM *>( hom )->Depth( x, y ) ) )
      {
        return false;
      }
      if ( const_cast<HOM *>( hom )->Map( x, y ) > OPACITY_THRESHOLD )
      {
        nOpaques++;
      }
    }
  }

  int iArea = ( ( xMax - xMin ) * ( yMax - yMin ) );
  if ( nOpaques < iArea )
  {
    if ( hom->prev != NULL )
      return Occluded( bound, depth, hom->prev, scnWidth, scnHeight, false );
    return false;
  }
  return true;
}