⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 worldeditor.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 5 页
字号:

      // scale it
      pnt.convolve(scale);
      mat.mulP(pnt, &projPnts[i]);
   }

   glDisable(GL_CULL_FACE);
   glColor4ub(col.red, col.green, col.blue, col.alpha);
   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   glDisable(GL_DEPTH_TEST);

   //
   glBegin(GL_QUADS);
   for(U32 k = 0; k < 4; k++)
      glVertex3f(projPnts[k].x, projPnts[k].y, projPnts[k].z);
   glEnd();
   glDisable(GL_BLEND);
   glEnable(GL_DEPTH_TEST);
}

//------------------------------------------------------------------------------



void WorldEditor::renderPlane(const Point3F & origin)
{
   if(!(mRenderPlane || mRenderPlaneHashes))
      return;

   glDisable(GL_CULL_FACE);
   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

   glColor4ub(mGridColor.red, mGridColor.green, mGridColor.blue, mGridColor.alpha);
   Point2F start(origin.x - mPlaneDim / 2, origin.y - mPlaneDim / 2);

   //
   if(mRenderPlane)
   {
      // draw the plane
      glBegin(GL_QUADS);
         glVertex3f(start.x, start.y, origin.z);
         glVertex3f(start.x, start.y + mPlaneDim, origin.z);
         glVertex3f(start.x + mPlaneDim, start.y + mPlaneDim, origin.z);
         glVertex3f(start.x + mPlaneDim, start.y, origin.z);
      glEnd();
   }

   //
   if(mRenderPlaneHashes)
   {
      if(mGridSize.x > 0)
      {
         U32 xSteps = (U32)(mPlaneDim / mGridSize.x);
         F32 hashStart = mCeil(start.x / mGridSize.x) * mGridSize.x;
         for(U32 i = 0; i < xSteps; i++)
         {
            glBegin(GL_LINE_LOOP);
            glVertex3f(hashStart + mGridSize.x * i, start.y, origin.z + 0.001f);
            glVertex3f(hashStart + mGridSize.x * i, start.y + mPlaneDim, origin.z + 0.001f);
            glEnd();
         }
      }

      if(mGridSize.y > 0)
      {
         U32 ySteps = (U32)(mPlaneDim / mGridSize.y);
         F32 hashStart = mCeil(start.y / mGridSize.y) * mGridSize.y;
         for(U32 i = 0; i < ySteps; i++)
         {
            glBegin(GL_LINE_LOOP);
            glVertex3f(start.x, hashStart + mGridSize.y * i, origin.z + 0.001f);
            glVertex3f(start.x + mPlaneDim, hashStart + mGridSize.y * i, origin.z + 0.001f);
            glEnd();
         }
      }
   }

   glDisable(GL_BLEND);
}



//------------------------------------------------------------------------------

void WorldEditor::renderMousePopupInfo()
{
   Point2I pos(mLastMouseEvent.mousePoint.x,
      mLastMouseEvent.mousePoint.y + mCurrentCursor->getExtent().y - mCurrentCursor->getHotSpot().y);

   if(mCurrentMode == mDefaultMode && !mMouseDragged)
      return;

   char buf[256];
   switch(mCurrentMode)
   {
      case Move:
      {
         if(!mSelected.size())
            return;

         Point3F pos = mObjectsUseBoxCenter ? mSelected.getBoxCentroid() : mSelected.getCentroid();
         dSprintf(buf, sizeof(buf), "x: %0.3f, y: %0.3f, z: %0.3f", pos.x, pos.y, pos.z);
         break;
      }

      case Rotate: {

         if(!bool(mHitObject) || (mSelected.size() != 1))
            return;

         // print out the angle-axis 'fo
         AngAxisF aa(mHitObject->getTransform());

         dSprintf(buf, sizeof(buf), "x: %0.3f, y: %0.3f, z: %0.3f, a: %0.3f",
            aa.axis.x, aa.axis.y, aa.axis.z, mRadToDeg(aa.angle));

         break;
      }

      case Scale: {

         if(!bool(mHitObject) || (mSelected.size() != 1))
            return;

         VectorF scale = mHitObject->getScale();

         Box3F box = mHitObject->getObjBox();
         box.min.convolve(scale);
         box.max.convolve(scale);

         box.max -= box.min;
         dSprintf(buf, sizeof(buf), "w: %0.3f, h: %0.3f, d: %0.3f", box.max.x, box.max.y, box.max.z);
         break;
      }

      default:
         return;
   }

   U32 width = mProfile->mFont->getStrWidth(buf);

   if(mRenderPopupBackground)
   {
      Point2I min(pos.x - width / 2 - 2, pos.y - 1);
      Point2I max(pos.x + width / 2 + 2, pos.y + mProfile->mFont->getHeight() + 1);

      dglDrawRectFill(min, max, mPopupBackgroundColor);
   }

	dglSetBitmapModulation(mPopupTextColor);
   dglDrawText(mProfile->mFont, Point2I(pos.x - width / 2, pos.y), buf);
}

//------------------------------------------------------------------------------

void WorldEditor::renderPaths(SimObject *obj)
{
   if (obj == NULL)
      return;
   bool selected = false;

   // Loop through subsets
   if (SimSet *set = dynamic_cast<SimSet*>(obj))
      for(SimSetIterator itr(set); *itr; ++itr) {
         renderPaths(*itr);
         if ((*itr)->isSelected())
            selected = true;
      }

   // Render the path if it, or any of it's immediate sub-objects, is selected.
   if (Path *path = dynamic_cast<Path*>(obj))
      if (selected || path->isSelected())
         renderSplinePath(path);
}


void WorldEditor::renderSplinePath(Path *path)
{
   // at the time of writing the path properties are not part of the path object
   // so we don't know to render it looping, splined, linear etc.
   // for now we render all paths splined+looping

   Vector<Point3F> positions;
   Vector<QuatF>   rotations;

   path->sortMarkers();
   CameraSpline spline;

   for(SimSetIterator itr(path); *itr; ++itr)
   {
      Marker *pathmarker = dynamic_cast<Marker*>(*itr);
      if (!pathmarker)
         continue;
      Point3F pos;
      pathmarker->getTransform().getColumn(3, &pos);

      QuatF rot;
      rot.set(pathmarker->getTransform());
      CameraSpline::Knot::Type type;
      switch (pathmarker->mKnotType)
      {
         case Marker::KnotTypePositionOnly:  type = CameraSpline::Knot::POSITION_ONLY; break;
         case Marker::KnotTypeKink:          type = CameraSpline::Knot::KINK; break;
         case Marker::KnotTypeNormal:
         default:                            type = CameraSpline::Knot::NORMAL; break;

      }

      CameraSpline::Knot::Path path;
      switch (pathmarker->mSmoothingType)
      {
         case Marker::SmoothingTypeLinear:   path = CameraSpline::Knot::LINEAR; break;
         case Marker::SmoothingTypeSpline:
         default:                            path = CameraSpline::Knot::SPLINE; break;

      }

      spline.push_back(new CameraSpline::Knot(pos, rot, 1.0f, type, path));
   }

   F32 t = 0.0f;
   S32 size = spline.size();
   if (size <= 1)
      return;

   // DEBUG
   //spline.renderTimeMap();

   if (path->isLooping())
   {
      CameraSpline::Knot *front = new CameraSpline::Knot(*spline.front());
      CameraSpline::Knot *back  = new CameraSpline::Knot(*spline.back());
      spline.push_back(front);
      spline.push_front(back);
      t = 1.0f;
      size += 2;
   }

   while (t < size - 1)
   {
      CameraSpline::Knot k;
      spline.value(t, &k);
      t = spline.advanceDist(t, 2.0f);

      VectorF a(-0.15f, -0.25f, 0.0f);
      VectorF b( 0.0f,  0.25f, 0.0f);
      VectorF c( 0.15f, -0.25f, 0.0f);
      VectorF t1, t2, t3;

      k.mRotation.mulP(a, &t1); t1 += k.mPosition;
      k.mRotation.mulP(b, &t2); t2 += k.mPosition;
      k.mRotation.mulP(c, &t3); t3 += k.mPosition;

      glEnable(GL_BLEND);
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

      // OUTLINE
      glColor4f(0, 1, 0, 1);
      glLineWidth(1);
      glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

      glBegin(GL_TRIANGLES);
      glVertex3f(t1.x, t1.y, t1.z);
      glVertex3f(t2.x, t2.y, t2.z);
      glVertex3f(t3.x, t3.y, t3.z);
      glEnd();

      // FILL
      glColor4f(0, 2, 0, 0.2);
      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

      glBegin(GL_TRIANGLES);
      glVertex3f(t1.x, t1.y, t1.z);
      glVertex3f(t2.x, t2.y, t2.z);
      glVertex3f(t3.x, t3.y, t3.z);
      glEnd();

      glDisable(GL_BLEND);
   }
}


//------------------------------------------------------------------------------
// render the handle/text/...
void WorldEditor::renderScreenObj(SceneObject * obj, Point2I sPos)
{
   // do not render control object stuff
   if(obj == getControlObject() || obj->isHidden())
      return;

   ClassInfo::Entry * entry = getClassEntry(obj);
   if(!entry)
      entry = &mDefaultClassEntry;

   TextureObject * bitmap;
   if(mRenderObjHandle)
   {
      // offset
      if(obj->isLocked())
         bitmap = entry->mLockedHandle ? entry->mLockedHandle : mDefaultClassEntry.mLockedHandle;
      else
      {
         if(mSelected.objInSet(obj))
            bitmap = entry->mSelectHandle ? entry->mSelectHandle : mDefaultClassEntry.mSelectHandle;
         else
            bitmap = entry->mDefaultHandle ? entry->mDefaultHandle : mDefaultClassEntry.mDefaultHandle;
      }

      sPos.x -= (bitmap->bitmapWidth / 2);
      sPos.y -= (bitmap->bitmapHeight / 2);
      dglClearBitmapModulation();
      dglDrawBitmap(bitmap, sPos);
   }

   //
   if(mRenderObjText)
   {

      const char * str = parseObjectFormat(obj, mObjTextFormat);

      Point2I extent(mProfile->mFont->getStrWidth(str), mProfile->mFont->getHeight());

      Point2I pos(sPos);

      if(mRenderObjHandle)
      {
         pos.x += (bitmap->bitmapWidth / 2) - (extent.x / 2);
         pos.y += (bitmap->bitmapHeight / 2) + 3;
      }
		dglSetBitmapModulation(mObjectTextColor);
      dglDrawText(mProfile->mFont, pos, str);
   }
}

//------------------------------------------------------------------------------
// axis gizmo stuff

void WorldEditor::calcAxisInfo()
{
   if(!mSelected.size())
      return;

   // get the centroid..
   mSelected.invalidateCentroid();
   Point3F centroid = mObjectsUseBoxCenter ? mSelected.getBoxCentroid() : mSelected.getCentroid();
   mAxisGizmoCenter = centroid;

   VectorF axisVector[3] = {
      VectorF(1,0,0),
      VectorF(0,1,0),
      VectorF(0,0,1)
   };

   // adjust to object space if just one object...
   if((mSelected.size() == 1) && !((mLastMouseEvent.modifier & SI_SHIFT) && (mCurrentMode == Move)))
   {
      const MatrixF & mat = mSelected[0]->getTransform();
      for(U32 i = 0; i < 3; i++)
      {
         VectorF tmp;
         mat.mulV(axisVector[i], &tmp);
         mAxisGizmoVector[i] = tmp;
         mAxisGizmoVector[i].normalizeSafe();
      }
   }
   else
      for(U32 i = 0; i < 3; i++)
         mAxisGizmoVector[i] = axisVector[i];

   // get the projected size...
   SceneObject * obj = getControlObject();
   if(!obj)
      return;

   //
   Point3F camPos;
   obj->getTransform().getColumn(3, &camPos);

   // assumes a 90deg FOV
   Point3F dir = mAxisGizmoCenter - camPos;
   mAxisGizmoProjLen = (F32(mAxisGizmoMaxScreenLen) / F32(getExtent().x)) * dir.magnitudeSafe() * mTan(mDegToRad(45.0));
}

bool WorldEditor::collideAxisGizmo(const Gui3DMouseEvent & event)
{
   if(!mAxisGizmoActive || !mSelected.size())
      return(false);

   // get the projected size...
   SceneObject * obj = getControlObject();
   if(!obj)
      return(false);

   //
   Point3F camPos;
   obj->getRenderTransform().getColumn(3, &camPos);

   // assumes a 90deg FOV
   Point3F dir = mAxisGizmoCenter - camPos;
   mAxisGizmoProjLen = (F32(mAxisGizmoMaxScreenLen) / F32(getExtent().x)) * dir.magnitudeSafe() * mTan(mDegToRad(45.0));

   dir.normalizeSafe();

   mAxisGizmoSelAxis = -1;

   // find axis to use...
   for(U32 i = 0; i < 3; i++)
   {
      VectorF up, normal;
      mCross(dir, mAxisGizmoVector[i], &up);
      mCross(up, mAxisGizmoVector[i], &normal);

      if(normal.isZero())
         break;

      PlaneF plane(mAxisGizmoCenter, normal);

      // width of the axis poly is 1/10 the run
      Point3F a = up * mAxisGizmoProjLen / 10;
      Point3F b = mAxisGizmoVector[i] * mAxisGizmoProjLen;

      Point3F poly [] = {
         Point3F(mAxisGizmoCenter + a),
         Point3F(mAxisGizmoCenter + a + b),
         Point3F(mAxisGizmoCenter - a + b),
         Point3F(mAxisGizmoCenter - a)
      };

      Point3F end = camPos + event.vec * mProjectDistance;
   	F32 t = plane.intersect(camPos, end);
      if(t >= 0 && t <= 1)
      {
         Point3F pos;
         pos.interpolate(camPos, end, t);

         // check if inside our 'poly' of this axis vector...
         bool inside = true;
         for(U32 j = 0; inside && (j < 4); j++)
         {
            U32 k = (j+1) % 4;
            VectorF vec1 = poly[k] - poly[j];
            VectorF vec2 = pos - poly[k];

            if(mDot(vec1, vec2) > 0.f)
               inside = false;
         }

         //
         if(inside)
         {
            mAxisGizmoSelAxis = i;
            return(true);
         }
      }
   }

   return(false);
}

//------------------------------------------------------------------------------

void WorldEditor::renderAxisGizmo()
{
   calcAxisInfo();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -