Example #1
0
/**
 * Sets the bounding box of the mesh to \a box and its center to \a center.
 */
void SoPolygon::computeBBox(SoAction *action, SbBox3f &box, SbVec3f &center)
{
    SoState*  state = action->getState();
    const SoCoordinateElement * coords = SoCoordinateElement::getInstance(state);
    if (!coords) return;
    const SbVec3f * points = coords->getArrayPtr3();
    if (!points) return;
    float maxX=-FLT_MAX, minX=FLT_MAX,
          maxY=-FLT_MAX, minY=FLT_MAX,
          maxZ=-FLT_MAX, minZ=FLT_MAX;
    int32_t len = coords->getNum();
    int32_t beg = startIndex.getValue();
    int32_t cnt = numVertices.getValue();
    int32_t end = beg + cnt;
    if (end <= len) {
        for (int32_t i=beg; i<end; i++) {
            maxX = std::max<float>(maxX,points[i][0]);
            minX = std::min<float>(minX,points[i][0]);
            maxY = std::max<float>(maxY,points[i][1]);
            minY = std::min<float>(minY,points[i][1]);
            maxZ = std::max<float>(maxZ,points[i][2]);
            minZ = std::min<float>(minZ,points[i][2]);
        }

        box.setBounds(minX,minY,minZ,maxX,maxY,maxZ);
        center.setValue(0.5f*(minX+maxX),0.5f*(minY+maxY),0.5f*(minZ+maxZ));
    }
    else {
        box.setBounds(SbVec3f(0,0,0), SbVec3f(0,0,0));
        center.setValue(0.0f,0.0f,0.0f);
    }
}
Example #2
0
// Doc in parent
void
SoVRMLCone::computeBBox(SoAction * COIN_UNUSED_ARG(action),
                        SbBox3f & box,
                        SbVec3f & center)
{
  float r = this->bottomRadius.getValue();
  float h = this->height.getValue();

  // Allow negative values.
  if (h < 0.0f) h = -h;
  if (r < 0.0f) r = -r;

  float half_height = h * 0.5f;

  // The SIDES are present, so just find the middle point and enclose
  // everything.
  if (this->side.getValue()) {
    center.setValue(0.0f, 0.0f, 0.0f);
    box.setBounds(SbVec3f(-r, -half_height, -r), SbVec3f(r, half_height, r));
  }
  // ..no SIDES, but we've still got the bottom (NB: OIV misses this case).
  else if (this->bottom.getValue()) {
    center.setValue(0.0f, -half_height, 0.0f);
    box.setBounds(SbVec3f(-r, -half_height, -r), SbVec3f(r, -half_height, r));
  }
  // ..no parts present. My confidence is shot -- I feel very small.
  else {
    center.setValue(0.0f, 0.0f, 0.0f);
    box.setBounds(SbVec3f(0.0f, 0.0f, 0.0f), SbVec3f(0.0f, 0.0f, 0.0f));
  }
}
Example #3
0
void
SoCylinder::computeBBox(SoAction *, SbBox3f &box, SbVec3f &center)
//
////////////////////////////////////////////////////////////////////////
{
    int		curParts = (parts.isIgnored() ? ALL : parts.getValue());

    if (curParts == 0)		// No parts at all!
	box.setBounds(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);

    else {
	float	r, h;
	SbVec3f	min, max;

	getSize(r, h);

	if (HAS_PART(curParts, SIDES | TOP))
	    max.setValue( r,  h,  r);
	else
	    max.setValue( r, -h,  r);

	if (HAS_PART(curParts, SIDES | BOTTOM))
	    min.setValue(-r, -h, -r);
	else
	    min.setValue(-r,  h, -r);

	box.setBounds(min, max);
    }

    center.setValue(0.0, 0.0, 0.0);
}
Example #4
0
int QilexDoc::doc_new_kinematic_hand(ct_new_kinematic_chain *data)
{
   int error = 0;
   int tipus = 0;
   void * buffer ; //char *buffer;
   char *buftemp = (char*)malloc(1024);

   SoOutput out;

   size_t sizeModel = 0;

   SoSeparator *kinechain = new SoSeparator;
   SoSeparator *kinetest = new SoSeparator;

   Rchain_hand *kineengine = new Rchain_hand();

   SoTransform *pos_rot = new SoTransform;
   SbVec3f joinax;

   joinax.setValue(SbVec3f(data->x,data->y,data->z));
   pos_rot->translation.setValue(joinax);
   pos_rot->rotation.setValue(SbVec3f(data->axeX, data->axeY, data->axeZ), (float) rad((double) data->angle));

   kinechain = readFile(data->QsModelFile.latin1(), tipus);

   if (kinechain == NULL) // no object read
   { return 1; }
   else  // ok, there's no object with the same name
   {
      error = kineengine->init_dat(data->QsDatFile.latin1()); //

      if (error == 0)
      {
         kinechain->ref();
         kinetest = (SoSeparator*)SoNode::getByName(data->QsName.latin1());

         if (kinetest==NULL)
         {
            //we need to put it in a buffer to write the xml file
            // if is Ok
            SoOutput out;
            out.setBuffer(buftemp, 1024, reallocCB);

            SoWriteAction wa1(&out);
            wa1.apply(kinechain);

            out.getBuffer(buffer, sizeModel);

            kinechain->insertChild(pos_rot, 0);
         }
         error = doc_insert_kinematic_hand(kineengine, kinechain);
      }
   }

   if (error==0)
   {
      writeXML_kineelement((char *)buffer, sizeModel, tipus, data, kineengine);
   }
   return error;
}
Example #5
0
bool RayTracer::depth_of_field(int i, int j, SbVec3f *position, SbVec3f *color){
    SbVec3f tempColor;
    float R = DISK_SIZE;
    float du;
    float dv;
    bool should_color ;
    int number_of_jitter_positions = NUMBER_OF_CAMERAS;

    if(depth_of_field_on == 0) {
            should_color = distribute_shade(i,j, position, color);
    }
    else{
        for(int k =0; k< number_of_jitter_positions ; k++){
            SbVec3f camera_position = *position;
            du = get_random_number();
            dv = get_random_number();
            camera_position = camera_position  + (du * R * pixel_width * this->u) + (dv * pixel_height * R * this->v);
            tempColor.setValue(0.0,0.0,0.0);
            should_color = distribute_shade(i, j, &camera_position,&tempColor);
            *color = *color + tempColor;
        }
        *color = *color/number_of_jitter_positions ;

    }
    return should_color;

}
Example #6
0
void
SoNurbsSurface::computeBBox(SoAction *action, SbBox3f &box, SbVec3f &center)
//
////////////////////////////////////////////////////////////////////////
{
    const SoCoordinateElement   *ce =
            SoCoordinateElement::getInstance(action->getState());
    int32_t			nCoords, numSurfCoords;
    int				j, curCoord;
    SbVec3f			tmpCoord;

    //
    // Loop through coordinates, keeping max bounding box and sum of coords
    // If the coordinates are rational, divide the first three values by
    // the fourth value before extending the bounding box.
    //
    numSurfCoords = numUControlPoints.getValue() *
                    numVControlPoints.getValue();
    nCoords = ce->getNum();

    // Check for a degenerate surface
    if ((numSurfCoords == 0) || (nCoords == 0))
        return;

    curCoord = 0;
    center.setValue(0.0, 0.0, 0.0);
    if (ce->is3D()) {
        for (j = 0; j < numSurfCoords; j++) {
            //
            // Wrap around if necessary
            //
            if (curCoord >= nCoords)
	        curCoord = 0;
            const SbVec3f &coord = ce->get3(curCoord);
            box.extendBy(coord);
            center += coord;
            curCoord++;
        }
    }
    else {
        for (j = 0; j < numSurfCoords; j++) {
            //
            // Wrap around if necessary
            //
            if (curCoord >= nCoords)
	        curCoord = 0;
            const SbVec4f &coord = ce->get4(curCoord);
            coord.getReal (tmpCoord);
            box.extendBy (tmpCoord);
            center += tmpCoord;
            curCoord++;
        }
    }

    center /= (float) numSurfCoords;
}
Example #7
0
/*! \param orientation
 *  \param[out] upVec
 *  \param[out] lookDir
 *  \param[out] upVecAngle
 */
void kCamera::splitOrientation(const SbRotation orientation, SbVec3f& upVec, SbVec3f& lookDir, double& upVecAngle)
{
	// Extrahieren der lookDir aus der aktuellen orientation
	lookDir.setValue(0.0, 0.0, -1.0); //! init to default lookat direction (DIRECTION!)
    orientation.multVec(lookDir, lookDir);
	lookDir.normalize();

	// Extrahieren des upVectors aus der aktuellen orientation
	upVec.setValue(0.0, 1.0, 0.0); // init to default up vector direction
	orientation.multVec(upVec, upVec);
	upVec.normalize();

	// Ermitteln des perfekten upVectors (upVector ohne zusätzliche Drehung um die Sichtachse)
	SbVec3f perfectUpVec;
	if (fabs(lookDir.dot(NormPlump))>(1.0-epsilon)) //! wenn lookDir und perfectUpVec parallel, dann gleich setzen (Vermeidung von Berechnungsfehlern
		perfectUpVec = upVec;
	else
		perfectUpVec = calcPerfectUpVector(lookDir,NormPlump);

	perfectUpVec.normalize();

	// a dot b = |a|*|b|+cos(a,b)
	double tempDot = upVec.dot(perfectUpVec); //! Es gab Fälle, in denen war .dot minimal größer als 1.0 -> acos = 1.#IND
	if (tempDot>1.0) tempDot = 1.0;	if (tempDot<-1.0) tempDot = -1.0;
	upVecAngle = acos(tempDot); //! 1.0 = Produkt der beiden Längen ... sind aber normalisiert


	// Ermittlung der Drehrichtung des Winkels und ggf. Erhöhung um 180Grad
	// Im R3 gibt es zuerst einmal keine positiven und negativen drehwinkel.
	// Erst wenn man die Ebene, die die beiden Vektoren definieren, orientiert, geht das.
	// Man kann also festlegen, dass der Winkel positiv ist, wenn Hesse-Normalenvektor der Ebene und Kreuzprodukt in dieselbe Richtung zeigen.
	if (getUpVecAngleDir(lookDir,upVec)>epsilon && (upVecAngle<(kBasics::PI-epsilon)))
		upVecAngle = kBasics::PI + (kBasics::PI - upVecAngle);

	// Vermeidung von Winkeln > 2*PI
	if (upVecAngle>(2*(kBasics::PI-epsilon)))
		upVecAngle = upVecAngle - 2*kBasics::PI;

	// Sehr kleine Winkel werden auf 0.0 gesetzt
	if (fabs(upVecAngle)<epsilon)
		upVecAngle = 0.0; //! sonst kommt es zu Dingen wie 1.#IND
}
Example #8
0
void
SbMatrix::multDirMatrix(const SbVec3f &src, SbVec3f &dst) const
{
    float	x,y,z;
    
    x = src[0]*matrix[0][0] + src[1]*matrix[1][0] + src[2]*matrix[2][0];
    y = src[0]*matrix[0][1] + src[1]*matrix[1][1] + src[2]*matrix[2][1];
    z = src[0]*matrix[0][2] + src[1]*matrix[1][2] + src[2]*matrix[2][2];
    
    dst.setValue(x, y, z);
}
Example #9
0
// Doc in parent
void
SoVRMLCylinder::computeBBox(SoAction * COIN_UNUSED_ARG(action),
                            SbBox3f & box,
                            SbVec3f & center)
{
  float r = this->radius.getValue();
  float h = this->height.getValue();

  // Allow negative values.
  if (r < 0.0f) r = -r;
  if (h < 0.0f) h = -h;

  // Either the SIDES are present, or we've at least got both the TOP
  // and BOTTOM caps -- so just find the middle point and enclose
  // everything.
  if (this->side.getValue() ||
      (this->bottom.getValue() &&
       this->top.getValue())) {
    center.setValue(0.0f, 0.0f, 0.0f);
    box.setBounds(SbVec3f(-r, -h/2.0f, -r), SbVec3f(r, h/2.0f, r));
  }
  // ..not a "full" cylinder, but we've got the BOTTOM cap.
  else if (this->bottom.getValue()) {
    center.setValue(0.0f, -h/2.0f, 0.0f);
    box.setBounds(SbVec3f(-r, -h/2.0f, -r), SbVec3f(r, -h/2.0f, r));
  }
  // ..not a "full" cylinder, but we've got the TOP cap.
  else if (this->top.getValue()) {
    center.setValue(0.0f, h/2.0f, 0.0f);
    box.setBounds(SbVec3f(-r, h/2.0f, -r), SbVec3f(r, h/2.0f, r));
  }
  // ..no parts present. My confidence is shot -- I feel very small.
  else {
    center.setValue(0.0f, 0.0f, 0.0f);
    box.setBounds(SbVec3f(0.0f, 0.0f, 0.0f), SbVec3f(0.0f, 0.0f, 0.0f));
  }
}
Example #10
0
void
SbMatrix::multVecMatrix(const SbVec3f &src, SbVec3f &dst) const
{
    float	x,y,z,w;
    
    x = src[0]*matrix[0][0] + src[1]*matrix[1][0] +
	src[2]*matrix[2][0] + matrix[3][0];
    y = src[0]*matrix[0][1] + src[1]*matrix[1][1] +
	src[2]*matrix[2][1] + matrix[3][1];
    z = src[0]*matrix[0][2] + src[1]*matrix[1][2] +
	src[2]*matrix[2][2] + matrix[3][2];
    w = src[0]*matrix[0][3] + src[1]*matrix[1][3] +
	src[2]*matrix[2][3] + matrix[3][3];
    
    dst.setValue(x/w, y/w, z/w);
}
Example #11
0
void
SbMatrix::multMatrixVec(const SbVec3f &src, SbVec3f &dst) const
{
    float	x,y,z,w;
    
    x = matrix[0][0]*src[0] + matrix[0][1]*src[1] +
	matrix[0][2]*src[2] + matrix[0][3];
    y = matrix[1][0]*src[0] + matrix[1][1]*src[1] +
	matrix[1][2]*src[2] + matrix[1][3];
    z = matrix[2][0]*src[0] + matrix[2][1]*src[1] +
	matrix[2][2]*src[2] + matrix[2][3];
    w = matrix[3][0]*src[0] + matrix[3][1]*src[1] +
	matrix[3][2]*src[2] + matrix[3][3];
    
    dst.setValue(x/w, y/w, z/w);
}
Example #12
0
// Doc in parent
void
SoVRMLBox::computeBBox(SoAction * action,
                       SbBox3f & COIN_UNUSED_ARG(box),
                       SbVec3f & center)
{
  center.setValue(0.0f, 0.0f, 0.0f);
  SbVec3f s = this->size.getValue();
  float w = s[0] * 0.5f;
  float h = s[1] * 0.5f;
  float d = s[2] * 0.5f;

  // Allow negative values.
  if (w < 0.0f) w = -w;
  if (h < 0.0f) h = -h;
  if (d < 0.0f) d = -d;

  box.setBounds(-w, -h, -d, w, h, d);
}
bool ObjMgrCommunicator::getObjAttributeVec3f(const string ObjID, const string LayerID, const string InfoID, SbVec3f& vec3f)
{
  omAttribute attr;
  if (getObjAttribute(ObjID,LayerID,InfoID, attr))
  {
    vector<string> VecSplit;
    kBasics::split(attr.getStringValue(),' ',3,&VecSplit);

    if (VecSplit.size()!=3)
    {
      kDebug::Debug("WrongSplitSize: " + kBasics::IntToString(VecSplit.size()),kDebug::DL_HIGH);
      return false;
    }

    vec3f.setValue(kBasics::StringToFloat(VecSplit[0]),kBasics::StringToFloat(VecSplit[1]),kBasics::StringToFloat(VecSplit[2]));
    return true;
  }
  return false;
}
Example #14
0
void SoRing::computeBBox(SoAction*, SbBox3f& box, SbVec3f& BBcenter)
{
  float Xc, Yc;
  center.getValue().getValue(Xc,Yc);

  // centered at origin
  BBcenter.setValue(Xc, Yc, 0.);

  // bounding box
  float R = outerRadius.getValue();
  float theta = sweepAngle.getValue()*M_PI/180.F;

  float Xmin, Ymin, Ymax;
  if ( theta < M_PI_2 )
  {
    Ymin = 0;
    Ymax = R*sin(theta);
    Xmin = 0;
  }
  else if ( theta < M_PI )
  {
    Ymin = 0;
    Ymax = R;
    Xmin = R*cos(theta);
  }
  else if ( theta < 3*M_PI_2 )
  {
    Ymin = R*sin(theta);
    Ymax = R;
    Xmin = -R;
  }
  else
  {
    Xmin = -R;
    Ymin = -R;
    Ymax = R;
  }

  SbVec3f corner1(Xmin+Xc,Ymin+Yc,0);
  SbVec3f corner2(R+Xc,Ymax+Yc,0);
  box.setBounds(corner1,corner2);
}
Example #15
0
void RayTracer::trace_rays(){
	int i,j;
    SbVec3f pix_pos, d_vec;
    SbVec3f tempColor;
    bool should_color ;

	double a,b,c;
	float color_scale;
	SbVec3f color;
    std::vector<Pixel> image_row;
    color.setValue(0.0,0.0,0.0);
    std::cout<<"Complete ";
	for (i=0; i < y_resolution; i++){
	    if (i%20 == 0)
            std::cout<< i << "/"<<y_resolution<<" Complete"<<std::endl;
	    image_row.clear();
        for (j=0; j < x_resolution; j++) {
	        //bool should_color = distribute_shade(i, j, &(camera->position), &color);
	        bool should_color = depth_of_field(i, j, &(camera->position), &color);

	        //if()
            //pix_pos = calculate_pixel_location(i,j, 0.5, 0.5);
            //d_vec  = pix_pos - camera->position;
            //d_vec.normalize();
            //bool should_color = shade(&(camera->position), &d_vec, &color, 1);
            if(should_color)
            {
                image_row.push_back(Pixel(min(color[0]), min(color[1]), min(color[2])));
            }
            else
                image_row.push_back(Pixel(0,0,0));

        }
        image.push_back(image_row);
	}
	open_file();
	write_to_file(image);
	close_file();
	std::cout<<"Done Tracing"<<std::endl;
	return;
}
Example #16
0
// Write SbRotation to output stream. Used from SoSFRotation and
// SoMFRotation.
void
sosfrotation_write_value(SoOutput * out, const SbRotation & r)
{
  SbVec3f axis;
  float angle;
  r.getValue(axis, angle);

  // Handle invalid rotation specifications.
  if (axis.length() == 0.0f) {
    axis.setValue(0.0f, 0.0f, 1.0f);
    angle = 0.0f;
  }

  out->write(axis[0]);
  if(!out->isBinary()) out->write(' ');
  out->write(axis[1]);
  if(!out->isBinary()) out->write(' ');
  out->write(axis[2]);
  if(!out->isBinary()) out->write("  ");
  out->write(angle);
}
Example #17
0
bool RayTracer::depth_of_field(int i, int j, SbVec3f *position, SbVec3f *color){
    //SbVec3f pix_pos, d_vec;
    SbVec3f tempColor;
    float R = DISK_SIZE;
    float du;
    float dv;
    bool should_color ;
    int number_of_jitter_positions = NUMBER_OF_CAMERAS;

    if(depth_of_field_on == 0) {
          //  std::cout<<"No Depth of field";
            //depth of field off
            //pix_pos = calculate_pixel_location(i,j, 0.5, 0.5);
           // d_vec  = pix_pos - *position;
           // d_vec.normalize();
            should_color = distribute_shade(i,j, position, color);
    }
    else{
        for(int k =0; k< number_of_jitter_positions ; k++){
            SbVec3f camera_position = *position;
            du = get_random_number();
            dv = get_random_number();
            //du = (du ) * R;
            //dv = (dv ) * R;
            //std::cout<<pixel_height<<pixel_width <<std::endl;
            //camera_position = camera_position  + (du * R * this->u) + (dv * R * this->v);
            camera_position = camera_position  + (du * R * pixel_width * this->u) + (dv * pixel_height * R * this->v);
            //pix_pos = calculate_pixel_location(i,j, 0.5, 0.5);
            //d_vec  = pix_pos - (camera_position);
            //d_vec.normalize();
            tempColor.setValue(0.0,0.0,0.0);
            should_color = distribute_shade(i, j, &camera_position,&tempColor);
            *color = *color + tempColor;
        }
        *color = *color/number_of_jitter_positions ;

    }
    return should_color;

}
float MeshFillHole::findClosestPoint(const SbLine& ray, const TBoundary& polygon,
                                     unsigned long& vertex_index, SbVec3f& closestPoint) const
{
    // now check which vertex of the polygon is closest to the ray
    float minDist = FLT_MAX;
    vertex_index = ULONG_MAX;

    const MeshCore::MeshKernel & rMesh = myMesh->Mesh.getValue().getKernel();
    const MeshCore::MeshPointArray& pts = rMesh.GetPoints();
    for (TBoundary::const_iterator it = polygon.begin(); it != polygon.end(); ++it) {
        SbVec3f vertex;
        const Base::Vector3f& v = pts[*it];
        vertex.setValue(v.x,v.y,v.z);
        SbVec3f point = ray.getClosestPoint(vertex);
        float distance = (vertex-point).sqrLength();
        if (distance < minDist) {
            minDist = distance;
            vertex_index = *it;
            closestPoint = vertex;
        }
    }

    return minDist;
}
Example #19
0
/*!
  Generates face normals for the faceset defined by \a coords
  and \a cind. 
*/
void
SoNormalCache::generatePerFace(const SbVec3f * const coords,
                               const unsigned int numcoords,
                               const int32_t * cind,
                               const int nv,
                               const SbBool ccw)
{
#if NORMALCACHE_DEBUG && COIN_DEBUG
    SoDebugError::postInfo("SoNormalCache::generatePerFace", "generating normals");
#endif

  this->clearGenerator();
  PRIVATE(this)->indices.truncate(0);
  PRIVATE(this)->normalArray.truncate(0, TRUE);

  const int32_t * cstart = cind;
  const int32_t * endptr = cind + nv;

  SbVec3f tmpvec;

  int maxcoordidx = numcoords - 1;

  while (cind + 2 < endptr) {
    int v0 = cind[0];
    int v1 = cind[1];
    int v2 = cind[2];

    if (v0 < 0 || v1 < 0 || v2 < 0 ||
        v0 > maxcoordidx || v1 > maxcoordidx || v2 > maxcoordidx) {
#if COIN_DEBUG
      SoDebugError::postWarning("SoNormalCache::generatePerFace",
                                "Polygon with less than three valid "
                                "vertices detected. (offset: %d, [%d %d %d]). "
                                "Should be within [0, %d].",
                                cind - cstart, v0, v1, v2, maxcoordidx);
#endif // COIN_DEBUG

       // Insert dummy normal for robustness
      SbVec3f dummynormal;
      dummynormal.setValue(0.0f, 0.0f, 0.0f);
      PRIVATE(this)->normalArray.append(dummynormal);

      // Skip ahead to next possible index
      if (cind[0] < 0 || cind[0] > maxcoordidx) {
        cind += 1;
      }
      else if (cind[1] < 0 || cind[1] > maxcoordidx) {
        cind += 2;
      }
      else if (cind + 3 < endptr && (cind[2] < 0 || cind[2] > maxcoordidx)) {
        cind += 3;
      }
      else {
        cind += 3; // For robustness check after while loop
        break;
      }

      continue;
    }
    
    if (cind + 3 >= endptr || cind[3] < 0 || cind[3] > maxcoordidx) { // triangle
      if (!ccw)
        tmpvec = (coords[v0] - coords[v1]).cross(coords[v2] - coords[v1]);
      else
        tmpvec = (coords[v2] - coords[v1]).cross(coords[v0] - coords[v1]);

      // Be robust when it comes to erroneously specified triangles.
      if ((tmpvec.normalize() == 0.0f) && coin_debug_extra()) {
        static uint32_t normgenerrors_face = 0;
        if (normgenerrors_face < 1) {
          SoDebugError::postWarning("SoNormalCache::generatePerFace",
                                    "Erroneous triangle specification in model "
                                    "(indices= [%d, %d, %d], "
                                    "coords=<%f, %f, %f>, <%f, %f, %f>, <%f, %f, %f>) "
                                    "(this warning will be printed only once, "
                                    "but there might be more errors).",
                                    v0, v1, v2,
                                    coords[v0][0], coords[v0][1], coords[v0][2],
                                    coords[v1][0], coords[v1][1], coords[v1][2],
                                    coords[v2][0], coords[v2][1], coords[v2][2]);
        }
        normgenerrors_face++;
      }
      
      PRIVATE(this)->normalArray.append(tmpvec);
      cind += 4; // goto next triangle/polygon
    }
    else { // more than 3 vertices
      // use Newell's method to calculate normal vector
      const SbVec3f * vert1, * vert2;
      tmpvec.setValue(0.0f, 0.0f, 0.0f);
      vert2 = coords + v0;
      cind++; // v0 is already read

      // The cind < endptr check makes us robust with regard to a
      // missing "-1" termination of the coordIndex field of the
      // IndexedShape nodetype.
      while (cind < endptr && *cind >= 0 && *cind <= maxcoordidx) {
        vert1 = vert2;
        vert2 = coords + *cind++;
        tmpvec[0] += ((*vert1)[1] - (*vert2)[1]) * ((*vert1)[2] + (*vert2)[2]);
        tmpvec[1] += ((*vert1)[2] - (*vert2)[2]) * ((*vert1)[0] + (*vert2)[0]);
        tmpvec[2] += ((*vert1)[0] - (*vert2)[0]) * ((*vert1)[1] + (*vert2)[1]);
      }

      vert1 = vert2;  // last edge (back to v0)
      vert2 = coords + v0;
      tmpvec[0] += ((*vert1)[1] - (*vert2)[1]) * ((*vert1)[2] + (*vert2)[2]);
      tmpvec[1] += ((*vert1)[2] - (*vert2)[2]) * ((*vert1)[0] + (*vert2)[0]);
      tmpvec[2] += ((*vert1)[0] - (*vert2)[0]) * ((*vert1)[1] + (*vert2)[1]);

      // Be robust when it comes to erroneously specified polygons.
      if ((tmpvec.normalize() == 0.0f) && coin_debug_extra()) {
        static uint32_t normgenerrors_face = 0;
        if (normgenerrors_face < 1) {
          SoDebugError::postWarning("SoNormalCache::generatePerFace",
                                    "Erroneous polygon specification in model. "
                                    "Unable to generate normal; using dummy normal. "
                                    "(this warning will be printed only once, "
                                    "but there might be more errors).");
        }
        normgenerrors_face++;
      }

      PRIVATE(this)->normalArray.append(ccw ? tmpvec : -tmpvec);
      cind++; // skip the -1
    }
  }

  if (endptr - cind > 0) {
#if COIN_DEBUG
    SoDebugError::postWarning("SoNormalCache::generatePerFace", "Face "
                              "specification did not end with a valid "
                              "polygon. Too few points");
#endif // COIN_DEBUG
    SbVec3f dummynormal;
    dummynormal.setValue(0.0f, 0.0f, 0.0f);
    PRIVATE(this)->normalArray.append(dummynormal);
  }

  if (PRIVATE(this)->normalArray.getLength()) {
    PRIVATE(this)->normalData.normals = PRIVATE(this)->normalArray.getArrayPtr();
    PRIVATE(this)->numNormals = PRIVATE(this)->normalArray.getLength();
  }

#if NORMALCACHE_DEBUG && COIN_DEBUG // debug
  SoDebugError::postInfo("SoNormalCache::generatePerFace",
                         "generated normals per face: %p %d",
                         PRIVATE(this)->normalData.normals, PRIVATE(this)->numNormals);
#endif // debug
}
Example #20
0
// internal callback
void InvPlaneMover::dragFinishCB(void *me, SoDragger *drag)
{

    InvPlaneMover *mee = static_cast<InvPlaneMover *>(me);

    if (mee->show_)
    {

        SbVec3f t = ((SoJackDragger *)drag)->translation.getValue();

        int i;
        for (i = 0; i < 3; ++i)
            t[i] *= mee->scale_->scaleFactor.getValue()[i];

        SbRotation r = ((SoJackDragger *)drag)->rotation.getValue();

        SbVec3f n;
        SbVec3f ax;
        float angle;
        r.getValue(ax, angle);

        SbVec3f axN;
        mee->fullRot_->rotation.getValue().multVec(ax, axN);

        r.setValue(axN, angle);

        r.multVec(mee->nnn_, n);

        // we have to rotate the translation around the x-axis
        // (because we have a y-axis dragger)
        SbVec3f tt;
        n.normalize();

        // snap normal to the closest coordinate axis
        // here done by snaping it to the axis with the biggest projection onto it.
        if (mee->motionMode_ == InvPlaneMover::SNAP)
        {
            int axis;
            float mmax;
            int dir = 1;
            SbVec3f nn;

            if (n[0] * n[0] < n[1] * n[1])
            {
                axis = 1;
                mmax = n[1];
                if (n[1] < 0)
                    dir = -1;
                else
                    dir = +1;
                //dir = (int) copysign(1,n[1]);
            }
            else
            {
                axis = 0;
                mmax = n[0];
                if (n[0] < 0)
                    dir = -1;
                else
                    dir = +1;
                //dir = (int) copysign(1,n[0]);
            }
            if (mmax * mmax < n[2] * n[2])
            {
                axis = 2;
                if (n[2] < 0)
                    dir = -1;
                else
                    dir = +1;
                //dir = (int) copysign(1,n[2]);
            }

            switch (axis)
            {
            case 0:
                nn.setValue(1, 0, 0);
                break;
            case 1:
                nn.setValue(0, 1, 0);
                break;
            case 2:
                nn.setValue(0, 0, 1);
                break;
            }
            n = dir * nn;
        }

        tt = t[1] * n;

        float d;
        d = n.dot(tt + mee->distOffset_);

        float data[4];
        data[0] = n[0];
        data[1] = n[1];
        data[2] = n[2];
        data[3] = d;

        // send feedback message to contoller
        ((InvPlaneMover *)me)->sendFeedback(data);
    }
}
Example #21
0
int QilexDoc::doc_insert_geometric_object(QDomElement geom_element)
{
   int error = 0;
   const char * buffer;
    
   SbVec3f joinax;
   SoTransform *pos_rot = new SoTransform;

   float joinangle;
   float pos_x, pos_y, pos_z, pos_rx, pos_ry, pos_rz;

   QString data, name;

   QDomNode node;
   QDomElement element;
   QDomNodeList list;

   SoSeparator *geomelement = new SoSeparator;
   SoSeparator *geomtest = new SoSeparator;
   
   name = geom_element.attribute ("name", QString::null);

   data = geom_element.attribute ("pos_x", QString::null);
   pos_x = data.toFloat();

   data = geom_element.attribute ("pos_y", QString::null);
   pos_y = data.toFloat();

   data = geom_element.attribute ("pos_z", QString::null);
   pos_z = data.toFloat();

   data = geom_element.attribute ("pos_rx", QString::null);
   pos_rx = data.toFloat();

   data = geom_element.attribute ("pos_ry", QString::null);
   pos_ry = data.toFloat();

   data = geom_element.attribute ("pos_rz", QString::null);
   pos_rz = data.toFloat();

   data = geom_element.attribute ("pos_angle", QString::null);
   joinangle = data.toFloat();

   joinax.setValue(SbVec3f( pos_x, pos_y, pos_z));
   pos_rot->translation.setValue(joinax);
   pos_rot->rotation.setValue(SbVec3f(pos_rx, pos_ry, pos_rz), (float) rad((double)joinangle));
   
   list = geom_element.elementsByTagName ("model3d");
   if (list.length() == 1)
   {
      node = list.item(0);
      element = node.toElement();

      data = element.attribute ("format", QString::null);
      // some stuff to take care about the format

      data = element.attribute ("size", QString::null);
      size_t size = (size_t)data.toULong(0,10);
      buffer = new char[size];

      data = element.text();
      buffer = data.ascii();

      SoInput input;
      input.setBuffer((void*) buffer, size);

      if (input.isValidBuffer())
      {
         geomelement = SoDB::readAll(&input);
         if (geomelement == NULL)
            error = 10;
      }
      else
         {error = 8;} //   assigno un nombre diferent de 0
   }
   else
   { error =9; }// assigno un nombre diferent de 0

   if (error == 0)
   {
      geomelement->ref();
      geomtest = (SoSeparator*)SoNode::getByName(name.latin1());

      if (geomtest==NULL)
      {
         //we need to put it in a buffer to write the xml file
         // if is Ok
         geomelement->insertChild(pos_rot, 0);
         geomelement->setName(name.latin1());
         view->addObjectCell(geomelement);
      }
   }
   return error; 
}
Example #22
0
int QilexDoc::doc_insert_kinematic_chain(QDomElement kine_element)
{
   int error = 0;
   const char * buffer;

   QDomNodeList list;
   
   Rchain *kineengine = new Rchain;
   
   SoSeparator *kinechain = new SoSeparator;
   SoSeparator *kinetest = new SoSeparator;

   //Rchain *kineengine = new Rchain;
   SoTransform *pos_rot = new SoTransform;
   SbVec3f joinax;

   float joinangle;
   float pos_x, pos_y, pos_z, pos_rx, pos_ry, pos_rz;

   QString data, name;

   QDomNode node;
   QDomElement element;
   
   name = kine_element.attribute ("name", QString::null);
   data = kine_element.attribute ("kineengine", QString::null);
   // here put some stuff to select the kinechain engine

   data = kine_element.attribute ("pos_x", QString::null);
   pos_x = data.toFloat();

   data = kine_element.attribute ("pos_y", QString::null);
   pos_y = data.toFloat();
      
   data = kine_element.attribute ("pos_z", QString::null);
   pos_z = data.toFloat();

   data = kine_element.attribute ("pos_rx", QString::null);
   pos_rx = data.toFloat();

   data = kine_element.attribute ("pos_ry", QString::null);
   pos_ry = data.toFloat();

   data = kine_element.attribute ("pos_rz", QString::null);
   pos_rz = data.toFloat();

   data = kine_element.attribute ("pos_angle", QString::null);
   joinangle = data.toFloat();
      
   joinax.setValue(SbVec3f( pos_x, pos_y, pos_z));
   pos_rot->translation.setValue(joinax);
   pos_rot->rotation.setValue(SbVec3f(pos_rx, pos_ry, pos_rz), (float) rad((double)joinangle));

   list = kine_element.elementsByTagName ("kinechain");

   if (list.length() == 1)
   {
      node = list.item(0);
      element = node.toElement();
      error = kineengine->read_element_xml (element);
   }
   else
   { error =4;} // assigno un nombre diferrent de 0
      
   list = kine_element.elementsByTagName ("model3d");
   if (list.length() == 1)
   {
      node = list.item(0);
      element = node.toElement();
            
      data = element.attribute ("format", QString::null);
      // some stuff to take care about the format
            
      data = element.attribute ("size", QString::null);
      size_t size = (size_t)data.toULong(0,10);
      buffer = new char[size];
   
      data = element.text();
      buffer = data.ascii();

  /*    char *buffer2 = new char[size];
      for(unsigned i=0;i<size;i++)
         buffer2[i] = buffer[i];
    */                 
      SoInput input;
      input.setBuffer((void *)buffer, size);

      if (input.isValidBuffer())
      {
         kinechain = SoDB::readAll(&input);
         
         if (kinechain == NULL)
            error = 10;
      }
      else
         {error = 8;} //  assigno un nombre diferent de 0
   }
   else
   { error =9; }// assigno un nombre diferent de 0
      
   if (error == 0)
   {
      kinechain->ref();
      kinetest = (SoSeparator*)SoNode::getByName(name.latin1());

      if (kinetest==NULL)
      {
         //we need to put it in a buffer to write the xml file
         // if is Ok
         kinechain->insertChild(pos_rot, 0);
         kinechain->setName(name.latin1());
         
         error = doc_insert_kinematic_chain(kineengine, kinechain);
      }
   }
   else {error = 5;}
   
   
   return error;
}
Example #23
0
int QilexDoc::doc_new_grasping_object(ct_new_grasping_object *data)
{
   int error = 0;
   int tipus = 0;

   void *buffer; //char *buffer;
   char *buftemp = (char*)malloc(1024);
   size_t sizeModel = 0;;

   SoSeparator *object = new SoSeparator;
   SoSeparator *objecttest = new SoSeparator;


   SoTransform *pos_rot = new SoTransform;
   SbVec3f joinax;
   SbVec3f joingrasp0;
   SbVec3f joingrasp1;
   SbVec3f joingrasp2;
   SbVec3f joingrasp3;

   joinax.setValue(SbVec3f(data->x,data->y,data->z));
   pos_rot->translation.setValue(joinax);
   pos_rot->recenter(joinax);
   pos_rot->rotation.setValue(SbVec3f(data->axeX, data->axeY, data->axeZ), (float) rad((double) data->angle));
   object = readFile(data->QsModelFile.latin1(), tipus);


   if (object == NULL) // no object read
   {
      error = 1 ;
   }
   else  // ok, there's no object with the same name
   {
      error = read_grasp_points(data);

      SoMaterial *bronze = new SoMaterial;
      bronze->ambientColor.setValue(0.33,0.22,0.27);
      bronze->diffuseColor.setValue(0.78,0.57,0.11);
      bronze->specularColor.setValue(0.99,0.94,0.81);
      bronze->shininess=0.28;

      SoSphere *grasp_sphere = new SoSphere;
      grasp_sphere->radius=7.0;

      SoFont *font = new SoFont;
      font->size.setValue(28);
      font->name.setValue("Times-Roman");
      SoSeparator *grasp_sep0 = new SoSeparator;
      SoTransform *grasp_transf0 = new SoTransform;
      SoSeparator *text0 = new SoSeparator;
      SoText2 *label_text0 = new SoText2;
      SoSeparator *grasp_sep1 = new SoSeparator;
      SoTransform *grasp_transf1 = new SoTransform;
      SoSeparator *text1 = new SoSeparator;
      SoText2 *label_text1 = new SoText2;
      SoSeparator *grasp_sep2 = new SoSeparator;
      SoTransform *grasp_transf2 = new SoTransform;
      SoSeparator *text2 = new SoSeparator;
      SoText2 *label_text2 = new SoText2;
      SoSeparator *grasp_sep3 = new SoSeparator;
      SoTransform *grasp_transf3 = new SoTransform;
      SoSeparator *text3 = new SoSeparator;
      SoText2 *label_text3 = new SoText2;

      //for (int i=0;i<data->num_point;i++)
      //{
       joingrasp0.setValue(SbVec3f(data->grasp_points[0].px,data->grasp_points[0].py,data->grasp_points[0].pz));
       grasp_transf0->translation.setValue(joingrasp0);
       grasp_transf0->recenter(joingrasp0);
       label_text0->string=" 1";
       text0->addChild(font);
       text0->addChild(label_text0);
       grasp_sep0->addChild(bronze);
       grasp_sep0->addChild(grasp_transf0);
       grasp_sep0->addChild(grasp_sphere);
       grasp_sep0->addChild(text0);
       //grasp_sep0->addChild(line0);
       joingrasp1.setValue(SbVec3f(data->grasp_points[1].px,data->grasp_points[1].py,data->grasp_points[1].pz));
       grasp_transf1->translation.setValue(joingrasp1);
       grasp_transf1->recenter(joingrasp1);
       label_text1->string=" 2";
       text1->addChild(font);
       text1->addChild(label_text1);
       grasp_sep1->addChild(bronze);
       grasp_sep1->addChild(grasp_transf1);
       grasp_sep1->addChild(grasp_sphere);
       grasp_sep1->addChild(text1);
       joingrasp2.setValue(SbVec3f(data->grasp_points[2].px,data->grasp_points[2].py,data->grasp_points[2].pz));
       grasp_transf2->translation.setValue(joingrasp2);
       grasp_transf2->recenter(joingrasp2);
       label_text2->string=" 3";
       text2->addChild(font);
       text2->addChild(label_text2);
       grasp_sep2->addChild(bronze);
       grasp_sep2->addChild(grasp_transf2);
       grasp_sep2->addChild(grasp_sphere);
       grasp_sep2->addChild(text2);
       joingrasp3.setValue(SbVec3f(data->grasp_points[3].px,data->grasp_points[3].py,data->grasp_points[3].pz));
       grasp_transf3->translation.setValue(joingrasp3);
       grasp_transf3->recenter(joingrasp3);
       label_text3->string=" 4";
       text3->addChild(font);
       text3->addChild(label_text3);
       grasp_sep3->addChild(bronze);
       grasp_sep3->addChild(grasp_transf3);
       grasp_sep3->addChild(grasp_sphere);
       grasp_sep3->addChild(text3);
       //object->addChild(grasp_sep);
      //}
      if (error == 0)
      {
      object->ref();
      objecttest = (SoSeparator*)SoNode::getByName(data->QsName.latin1());

      if (objecttest==NULL)
      {

         SoOutput out;
         out.setBuffer(buftemp, 1024, reallocCB);

         SoWriteAction wa1(&out);
         wa1.apply(object);

         out.getBuffer(buffer, sizeModel);

         object->setName(data->QsName.latin1());
	 //grasp_object->addChild(model_object);
	 object->addChild(grasp_sep0);
	 object->addChild(grasp_sep1);
	 object->addChild(grasp_sep2);
	 object->addChild(grasp_sep3);
         object->insertChild(pos_rot, 0);

         view->addObjectCell(object);
         error = 0;

         //writeXML_geomelement((char *)buffer, sizeModel, tipus, data);
	 //S'ha de canviar!!!!!
      }
      else
      {
         object->unref();
         error = 3;
      }
      }
   }
   return error;
}
Example #24
0
int QilexDoc::doc_new_geometric_object(ct_new_geometric_object *data)
{
   int error = 0;
   int tipus = 0;

   void *buffer; //char *buffer;
   char *buftemp = (char*)malloc(1024);
   size_t sizeModel = 0;;

   SoSeparator *object = new SoSeparator;
   SoSeparator *objecttest = new SoSeparator;


   SoTransform *pos_rot = new SoTransform;
   SbVec3f joinax;


   joinax.setValue(SbVec3f(data->x,data->y,data->z));
   pos_rot->translation.setValue(joinax);
   pos_rot->recenter(joinax);
   pos_rot->rotation.setValue(SbVec3f(data->axeX, data->axeY, data->axeZ), (float) rad((double) data->angle));
   object = readFile(data->QsModelFile.latin1(), tipus);


   if (object == NULL) // no object read
   {
      error = 1 ;
   }
   else  // ok, there's no object with the same name
   {
      object->ref();
      objecttest = (SoSeparator*)SoNode::getByName(data->QsName.latin1());

      if (objecttest==NULL)
      {

         SoOutput out;
         out.setBuffer(buftemp, 1024, reallocCB);

         SoWriteAction wa1(&out);
         wa1.apply(object);

         out.getBuffer(buffer, sizeModel);

         object->setName(data->QsName.latin1());
         object->insertChild(pos_rot, 0);

         view->addObjectCell(object);
         error = 0;

         writeXML_geomelement((char *)buffer, sizeModel, tipus, data);
      }
      else
      {
         object->unref();
         error = 3;
      }
   }

   return error;
}
Example #25
0
  static void generate_sphere(const float radius,
                              const int numstacks,
                              const int numslices,
                              SoShape * const shape,
                              SoAction * const action) {
    int stacks = numstacks;
    int slices = numslices;

    if (stacks < 3) stacks = 3;
    if (slices < 4) slices = 4;

    if (slices > 128) slices = 128;

    // used to cache last stack's data
    SbVec3f coords[129];
    SbVec3f normals[129];
    float S[129];

    int i, j;
    float rho;
    float drho;
    float theta;
    float dtheta;
    float tc, ts;
    SbVec3f tmp;

    drho = float(M_PI) / (float) (stacks-1);
    dtheta = 2.0f * float(M_PI) / (float) slices;

    float currs = 0.0f;
    float incs = 1.0f / (float)slices;
    rho = drho;
    theta = 0.0f;
    tc = (float) cos(rho);
    ts = - (float) sin(rho);
    tmp.setValue(0.0f,
                 tc,
                 ts);
    normals[0] = tmp;
    tmp *= radius;
    coords[0] = tmp;
    S[0] = currs;
    float dT = 1.0f / (float) (stacks-1);
    float T = 1.0f - dT;

    SoPrimitiveVertex vertex;
    shape->beginShape(action, SoShape::TRIANGLES);

    for (j = 1; j <= slices; j++) {
      vertex.setNormal(SbVec3f(0.0f, 1.0f, 0.0f));
      vertex.setTextureCoords(SbVec2f(currs + 0.5f * incs, 1.0f));
      vertex.setPoint(SbVec3f(0.0f, radius, 0.0f));
      shape->shapeVertex(&vertex);

      vertex.setNormal(normals[j-1]);
      vertex.setTextureCoords(SbVec2f(currs, T));
      vertex.setPoint(coords[j-1]);
      shape->shapeVertex(&vertex);

      currs += incs;
      theta += dtheta;
      S[j] = currs;
      tmp.setValue(float(sin(theta))*ts,
                   tc,
                   float(cos(theta))*ts);

      normals[j] = tmp;
      tmp *= radius;
      coords[j] = tmp;

      vertex.setNormal(normals[j]);
      vertex.setTextureCoords(SbVec2f(currs, T));
      vertex.setPoint(coords[j]);
      shape->shapeVertex(&vertex);

    }
    shape->endShape();

    rho += drho;

    for (i = 2; i < stacks-1; i++) {
      tc = (float)cos(rho);
      ts = - (float) sin(rho);
      shape->beginShape(action, SoShape::QUAD_STRIP);
      theta = 0.0f;
      for (j = 0; j <= slices; j++) {
        vertex.setTextureCoords(SbVec2f(S[j], T));
        vertex.setNormal(normals[j]);
        vertex.setPoint(coords[j]);
        shape->shapeVertex(&vertex);

        vertex.setTextureCoords(SbVec2f(S[j], T-dT));
        tmp.setValue(float(sin(theta))*ts,
                     tc,
                     float(cos(theta))*ts);
        normals[j] = tmp;
        vertex.setNormal(tmp);
        tmp *= radius;
        coords[j] = tmp;
        theta += dtheta;
        vertex.setPoint(tmp);
        shape->shapeVertex(&vertex);
      }
      shape->endShape();
      rho += drho;
      T -= dT;
    }

    shape->beginShape(action, SoShape::TRIANGLES);
    for (j = 0; j < slices; j++) {
      vertex.setTextureCoords(SbVec2f(S[j], T));
      vertex.setNormal(normals[j]);
      vertex.setPoint(coords[j]);
      shape->shapeVertex(&vertex);

      vertex.setTextureCoords(SbVec2f(S[j]+incs*0.5f, 0.0f));
      vertex.setNormal(SbVec3f(0.0f, -1.0f, 0.0f));
      vertex.setPoint(SbVec3f(0.0f, -radius, 0.0f));
      shape->shapeVertex(&vertex);

      vertex.setTextureCoords(SbVec2f(S[j+1], T));
      vertex.setNormal(normals[j+1]);
      vertex.setPoint(coords[j+1]);
      shape->shapeVertex(&vertex);
    }
    shape->endShape();
  }
Example #26
0
/*!
  Generates per row normals for quad data.
*/
void
SoNormalCache::generatePerRowQuad(const SbVec3f * const coords,
                                  const unsigned int numcoords,
                                  const int vPerRow,
                                  const int vPerColumn,
                                  const SbBool ccw)
{
#if NORMALCACHE_DEBUG && COIN_DEBUG
  SoDebugError::postInfo("SoNormalCache::generatePerRowQuad", "generating normals");
#endif

  this->clearGenerator();
  PRIVATE(this)->normalArray.truncate(0, TRUE);
  SbVec3f n;

#if COIN_DEBUG
  if (vPerRow <= 1 || vPerColumn <= 1 || 
      static_cast<unsigned int>(vPerRow * vPerColumn) > numcoords) {
    SoDebugError::postWarning("SoNormalCache::generatePerRowQuad", "Illegal "
                              "facequad dimension: [%d %d] with %d coordinates "
                              "available. verticesPerRow and verticesPerColumn "
                              "should be > 1, and verticesPerRow * verticesPerColumn "
                              "<= number of coordinates available.", 
                              vPerRow, vPerColumn, numcoords);
  }
#endif // COIN_DEBUG

#define IDX(r, c) ((r)*(vPerRow)+(c))

  for (int i = 0; i < vPerColumn-1; i++) {
    n.setValue(0.0f, 0.0f, 0.0f);
    for (int j = 0; j < vPerRow-1; j++) {
      const unsigned int idx1 = IDX(i, j);
      const unsigned int idx2 = IDX(i+1, j);
      const unsigned int idx3 = IDX(i, j+1);

      if (idx2 < numcoords) { // Check largest index only
        n += (coords[idx2] - coords[idx1]).cross(coords[idx3] - coords[idx1]);
      }
    }

    // Be robust when it comes to erroneously specified polygons.
    if ((n.normalize() == 0.0f) && coin_debug_extra()) {
      static uint32_t normgenerrors_rowquad = 0;
      if (normgenerrors_rowquad < 1) {
        SoDebugError::postWarning("SoNormalCache::generatePerRowQuad",
                                  "Erroneous polygon specification in model. "
                                  "Unable to generate valid normal, adding null vector. "
                                  "(this warning will be printed only once, "
                                  "but there might be more errors).");
      }
      normgenerrors_rowquad++;
    }    
    PRIVATE(this)->normalArray.append(ccw ? -n : n);
  }
  
#undef IDX

  if (PRIVATE(this)->normalArray.getLength()) {
    PRIVATE(this)->normalData.normals = PRIVATE(this)->normalArray.getArrayPtr();
    PRIVATE(this)->numNormals = PRIVATE(this)->normalArray.getLength();
  }

#if NORMALCACHE_DEBUG && COIN_DEBUG
  SoDebugError::postInfo("SoNormalCache::generatePerRowQuad",
                         "generated normals per row quad: %p %d\n",
                         PRIVATE(this)->normalData.normals, PRIVATE(this)->numNormals);
#endif

}
Example #27
0
/*!
  Generates one normal per triangle strips (avarages all triangle normals).
*/
void
SoNormalCache::generatePerStrip(const SbVec3f * const coords,
                                const unsigned int numcoords,
                                const int32_t * cind,
                                const int nv,
                                const SbBool ccw)
{
#if NORMALCACHE_DEBUG && COIN_DEBUG
  SoDebugError::postInfo("SoNormalCache::generatePerStrip", "generating normals");
#endif

  this->clearGenerator();
  PRIVATE(this)->indices.truncate(0);
  PRIVATE(this)->normalArray.truncate(0, TRUE);

  const int32_t * cstart = cind;
  const int32_t * endptr = cind + nv;

  const SbVec3f * c0, * c1, * c2;
  SbVec3f n;

  SbBool flip = ccw;

  const int maxcoordidx = numcoords - 1;

  while (cind + 2 < endptr) {
    if (cind[0] < 0 || cind[1] < 0 || cind[2] < 0 ||
        cind[0] > maxcoordidx || cind[1] > maxcoordidx || cind[2] > maxcoordidx) {
#if COIN_DEBUG
      SoDebugError::postWarning("SoNormalCache::generatePerStrip", "Erroneous "
                                "coordinate index detected (offset: %d, [%d %d %d]). Should be "
                                "within [0, %d].",
                                cind - cstart, *(cind), *(cind+1), *(cind+2), maxcoordidx);
#endif // COIN_DEBUG
      // Insert dummy normal for robustness
      SbVec3f dummynormal;
      dummynormal.setValue(0.0f, 0.0f, 0.0f);
      PRIVATE(this)->normalArray.append(dummynormal);

      // Skip to next possibly valid index
      if (cind[0] < 0 || cind[0] > maxcoordidx) {
        cind += 1;
      }
      else if (cind[1] < 0 || cind[1] > maxcoordidx) {
        cind += 2;
      }
      else if (cind + 3 < endptr && (cind[2] < 0 || cind[2] > maxcoordidx)) {
        cind += 3;
      }
      else {
        cind += 3; // For robustness check after while loop
        break;
      }

      continue;
    }
    
    flip = ccw;
    c0 = &coords[*cind++];
    c1 = &coords[*cind++];
    c2 = &coords[*cind++];

    if (!flip)
      n = (*c0 - *c1).cross(*c2 - *c1);
    else
      n = (*c2 - *c1).cross(*c0 - *c1);

    int idx = cind < endptr ? *cind++ : -1;
    while (idx >= 0 && idx <= maxcoordidx) {
      c0 = c1;
      c1 = c2;
      c2 = &coords[idx];
      flip = !flip;
      if (!flip)
        n += (*c0 - *c1).cross(*c2 - *c1);
      else
        n += (*c2 - *c1).cross(*c0 - *c1);
      idx = cind < endptr ? *cind++ : -1;
    }

#if COIN_DEBUG
    if (idx > maxcoordidx) {
      static uint32_t normgenerrors_strip = 0;
      if (normgenerrors_strip < 1) {
        SoDebugError::postWarning("SoNormalCache::generatePerStrip",
                                  "Erroneous polygon specification in model. "
                                  "Index out of bounds: %d. Max index: %d. "
                                  "(this warning will be printed only once, "
                                  "but there might be more errors).", 
                                  idx, maxcoordidx);
      }
      normgenerrors_strip++;
    }
#endif // COIN_DEBUG

    if ((n.normalize() == 0.0f) && coin_debug_extra()) {
      static uint32_t normgenerrors_strip = 0;
      if (normgenerrors_strip < 1) {
        SoDebugError::postWarning("SoNormalCache::generatePerStrip",
                                  "Erroneous polygon specification in model.  "
                                  "Unable to generate non-zero normal. Using "
                                  "dummy normal. "
                                  "(this warning will be printed only once, "
                                  "but there might be more errors).");
      }
      normgenerrors_strip++;
    }
    
    PRIVATE(this)->normalArray.append(n);
  }

  if (endptr - cind > 0) {
#if COIN_DEBUG
    SoDebugError::postWarning("SoNormalCache::generatePerStrip", "Strip did "
                              "not end with a valid polygon. Too few points");
#endif // COIN_DEBUG
    SbVec3f dummynormal;
    dummynormal.setValue(0.0, 0.0, 0.0);
    PRIVATE(this)->normalArray.append(dummynormal);
  }

  if (PRIVATE(this)->normalArray.getLength()) {
    PRIVATE(this)->normalData.normals = PRIVATE(this)->normalArray.getArrayPtr();
    PRIVATE(this)->numNormals = PRIVATE(this)->normalArray.getLength();
  }

#if NORMALCACHE_DEBUG && COIN_DEBUG
  SoDebugError::postInfo("SoNormalCache::generatePerStrip",
                         "generated normals per strip: %p %d\n",
                         PRIVATE(this)->normalData.normals, PRIVATE(this)->numNormals);
#endif

}
void SoXipCPUMprRender::computeBBox(SoAction *action, SbBox3f &box, SbVec3f &center)
{
	center.setValue(0.5, 0.5, 0.5);
	box.setBounds(0, 0, 0, 1, 1, 1);
}
Example #29
0
SbVec3f
SbLineProjector::project(const SbVec2f &point)
//
////////////////////////////////////////////////////////////////////////
{
    // Convert two line points to world space
	SbLine worldLine;
	workingToWorld.multLineMatrix( line, worldLine );
	SbVec3f wldPt1 = worldLine.getPosition();
	SbVec3f wldDir = worldLine.getDirection();
	SbVec3f wldPt2 = wldPt1 + wldDir;

    // Convert two line points to normalized screen space.
	SbVec3f nrmScnPt1, nrmScnPt2;
	viewVol.projectToScreen( wldPt1, nrmScnPt1 );
	viewVol.projectToScreen( wldPt2, nrmScnPt2 );

    // Convert two line points and input point 
    // to viewPlane space, a screen space that's got view plane's aspect ratio:
	float vvW  = (viewVol.getWidth()  == 0.0) ? 1 : viewVol.getWidth();
	float vvH  = (viewVol.getHeight() == 0.0) ? 1 : viewVol.getHeight();
	SbVec3f     vpPt1( nrmScnPt1[0] * vvW, nrmScnPt1[1] * vvH, 0);
	SbVec3f     vpPt2( nrmScnPt2[0] * vvW, nrmScnPt2[1] * vvH, 0);
	SbVec3f vpInPoint(     point[0] * vvW,     point[1] * vvH, 0);

    // Create the viewPlaneLine -- our line expressed in viewPlane space:
        SbLine  viewPlaneLine( vpPt1, vpPt2 );

    // In viewplane space, find the closest point on our line to the cursor.
	SbVec3f vpClosestPt = viewPlaneLine.getClosestPoint( vpInPoint );
	vpClosestPt.setValue( vpClosestPt[0], vpClosestPt[1], 0 );

    // If we've got a perspective view, we may need to clamp the point we
    // choose so that it's not too close to the vanishing point.
    // Otherwise we'll just use our vpClosestPt

	SbVec3f vpClampedPt = vpClosestPt;

	if ( viewVol.getProjectionType() == SbViewVolume::PERSPECTIVE ) {

	// Find the vanishing point of our line in viewPlane space: 
	    // Convert the direction of our line from world space into space 
	    // after the affine matrix (i.e. just before the projection matrix)
	    SbMatrix vvAffine, vvProj;
	    viewVol.getMatrices( vvAffine, vvProj );
	    SbVec3f postAffineDir;
	    vvAffine.multDirMatrix( wldDir, postAffineDir ); 

	  // If the direction of the line is parallel to the view plane,
	  // then the z component of postAffineDir is 0.
	  // In this case, we will not need to clamp our point and moreover,
	  // if we try we'll wind up dividing by zero pretty soon.
	  if ( postAffineDir[2] != 0.0 ) {

	    // If we send a line out from (0,0,0) into the viewVolume towards 
	    // postAffineDir, it will vanish at the same point as any other line
	    // parallel to this direction.  Also, all points along this line 
	    // will project to the same point on the near (or far) plane.
	    // So a line connecting (0,0,0) and the point at postAffineDir will
	    // intersect the near plane at the vanishing point.  Transforming 
	    // any point on this line by vvProj will yield the same x,y result 
	    // and the z component will vary with depth.
	    // So multiply the postAffineDir as a vector through the projection
	    // matrix and use the x,y for the vanishing point.
	    SbVec3f projVanish;
	    vvProj.multVecMatrix( postAffineDir, projVanish );

	    // Convert from [-1,1] range to [0,1] range for normalized coords.
	    SbVec3f nrmScnVanish;
	    nrmScnVanish[0] = (1.0 + projVanish[0]) * 0.5;
	    nrmScnVanish[1] = (1.0 + projVanish[1]) * 0.5;

	    // Finally, get the vanishing point in viewPlane coords:
	    SbVec3f vpVanish( nrmScnVanish[0] * vvW, nrmScnVanish[1] * vvH, 0 );

#if 0
	    // Check that the vanishing point is correct:
	    // Project nrmScnVanish on the plane to see if it goes along wldDir:
	    SbVec2f nrmScnVanish2( nrmScnVanish[0], nrmScnVanish[1] );
	    SbLine vanishWorldLine;
	    viewVol.projectPointToLine( nrmScnVanish2, vanishWorldLine );
	    SbVec3f test = vanishWorldLine.getDirection();
	    fprintf(stderr,"wldDir = %f %f %f\n",wldDir[0],wldDir[1],wldDir[2]);
	    fprintf(stderr,"checkDir = %f %f %f\n", test[0], test[1],test[2]);
#endif

	// The points vpPt1 and vpPt2 define the line in viewPlane space.
	// We can't go on the other side of the vanishing point from these 
	// defining points in screen space or the point will be undefined when 
	// we cast it into world space.
	// So clamp our selected point to lie on vpPt1's side of the vanishing 
	// point.  Since points near the vanishing point will also be incredibly
	// far away, introduce an (arbitrary) metric, VANISH_DELTA.
	// Our selection must be more than VANISH_DELTA times the average of
	// viewVolumeHeight and viewVolumeWidth from the vanishing point.
#define VANISH_DELTA .01
	    float vanishSafetyDist = VANISH_DELTA * .5 * (vvW + vvH);
#undef VANISH_DELTA
	    // Make pt0, the point from which we measure distances along vpLine.
	    // It will be one extra unit away from vpVanish than safetyDist
	    SbVec3f pt0 = viewPlaneLine.getPosition();
	    pt0.setValue( pt0[0], pt0[1], 0 );
	    SbVec3f pt0ToVanishDir = vpVanish - pt0;
	    pt0ToVanishDir.normalize();
	    float   pt0ToVanishDist = vanishSafetyDist + 1.0;
	    pt0 = vpVanish - pt0ToVanishDist * pt0ToVanishDir;

	    // Get vector and dist from pt0 to vpClosestPt
	    SbVec3f pt0ToClosest = vpClosestPt - pt0;
	    float   pt0ToClosestDist = pt0ToClosest.length();

	    // If vpClosestPt is too far from pt0, clamp it:
	    float   clampDist = pt0ToVanishDist - vanishSafetyDist;
	    if (    (pt0ToClosestDist > clampDist) 
		 && (pt0ToClosest.dot(pt0ToVanishDir) > 0.0) ) {
		vpClampedPt = pt0 + clampDist * pt0ToVanishDir;
	    }
	  }
	}

    // Convert result back into normalized screen space:
	SbVec2f nrmScnClampedPt( vpClampedPt[0] / vvW, vpClampedPt[1] / vvH);

    // Create a line in working space by projecting our point into the scene:
	SbVec3f result, whoCares;
	SbLine workingLine = getWorkingLine( nrmScnClampedPt );

    // Find point on the projector line closest to workingLine
	if (! line.getClosestPoints(workingLine, result, whoCares)) {
#ifdef DEBUG
	    SoDebugError::post("SbLineProjector::project",
			       "Couldn't get closest point");
#endif
    }

    return result;
}
void SoPrismKit::refresh()
{
    SoCoordinate3 *coords=(SoCoordinate3 *)(this->getPart("coords", TRUE));
    SoIndexedFaceSet *faces=(SoIndexedFaceSet *)(this->getPart("faces", TRUE));
    unsigned int i, k, nNumberOfVertices, nNumberOfCoordinates, nNextLimit, nNextIndex;
    k=0;

	// There must be at least three
	if (numFaces.getValue()<3)
        numFaces.setValue(3);

    nNumberOfVertices=numFaces.getValue();

    /// Generate vertices
    float angleSlope, angle, halfHeight;
    float x, y;
    SbVec3f nextPoint;
    angleSlope=(2*3.141592654)/nNumberOfVertices;
    angle=0;
    halfHeight=height.getValue()/2.0;
    for (i=0;i<nNumberOfVertices;i++)
    {
        x=radius.getValue()*(sin(angle));
        y=radius.getValue()*(cos(angle));
        nextPoint.setValue(x,-halfHeight,y);
        coords->point.set1Value(i,nextPoint);
        nextPoint.setValue(x,halfHeight,y);
        coords->point.set1Value(i+nNumberOfVertices,nextPoint);
        angle-=angleSlope;
    }

    nNextIndex=-1;
    nNextLimit=-1;
    
    // Create Bottom Face
    if (caps.getValue())
    {
        nNextIndex=0;
        nNextLimit=nNumberOfVertices;
        for (i=nNextIndex;i<nNextLimit;i++)
            faces->coordIndex.set1Value(i,i);
        faces->coordIndex.set1Value(nNextLimit,-1);
    
        // Create Top Face
        nNextIndex=nNextLimit+1;
        nNextLimit=nNextIndex+nNumberOfVertices;
        for (i=0;i<nNumberOfVertices;i++)
            faces->coordIndex.set1Value(i+nNextIndex,nNextLimit-i-2);
        faces->coordIndex.set1Value(nNextLimit,-1);
    }

    // This is the total of coordinates in 'coords'
    nNumberOfCoordinates=nNumberOfVertices*2;

	// Create the rest of the cylinder faces except for the last
	nNextIndex=nNextLimit+1;
	for (i=0;i<nNumberOfVertices-1;i++)
	{
		nNextLimit=(i*5+nNextIndex);
		faces->coordIndex.set1Value(nNextLimit,	    i);
		faces->coordIndex.set1Value(nNextLimit+1,	i+nNumberOfVertices);
		faces->coordIndex.set1Value(nNextLimit+2,	i+nNumberOfVertices+1);
		faces->coordIndex.set1Value(nNextLimit+3,   i+1);
		faces->coordIndex.set1Value(nNextLimit+4,	-1);
	}

	// Create the last of the cylinder faces
	i=nNumberOfVertices-1;
	nNextLimit=(i*5+nNextIndex);
	faces->coordIndex.set1Value(nNextLimit,	    nNumberOfVertices-1);
	faces->coordIndex.set1Value(nNextLimit+1,	nNumberOfVertices*2-1);
	faces->coordIndex.set1Value(nNextLimit+2,	nNumberOfVertices);
	faces->coordIndex.set1Value(nNextLimit+3,	0);
	faces->coordIndex.set1Value(nNextLimit+4,	-1);

}