void ribi::DrawCanvas::DrawArc( const double left, const double top, const double right, const double bottom, const boost::units::quantity<boost::units::si::plane_angle> startAngle, const boost::units::quantity<boost::units::si::plane_angle> spanAngle) noexcept { assert(left < right); assert(top < bottom); const double midx = (left + right) / 2.0; const double midy = (top + bottom) / 2.0; const double pi = boost::math::constants::pi<double>(); const double ray_horizontal = (right - left) / 2.0; const double ray_vertical = (bottom - top ) / 2.0; const double average_ray = (ray_horizontal + ray_vertical) / 2.0; const double arclength = average_ray * pi * 2.0 * (spanAngle.value() / (2.0 * pi)); const int n_steps = std::abs(static_cast<int>(arclength + 0.5)); if (n_steps == 0) return; assert(n_steps > 0); double angle { startAngle.value() }; const double dAngle = spanAngle.value() / static_cast<double>(n_steps); for (int i=0; i!=n_steps; ++i) { double x = midx + (std::sin(angle) * ray_horizontal); double y = midy - (std::cos(angle) * ray_vertical); DrawDot(x,y); angle += dAngle; } m_signal_changed(this); }
void ribi::DrawCanvas::DrawEllipse(const double left, const double top, const double right, const double bottom) noexcept { assert(left < right); assert(top < bottom); const double midx = (left + right) / 2.0; const double midy = (top + bottom) / 2.0; assert(midx > 0.0); const double pi = boost::math::constants::pi<double>(); const double ray_horizontal = (right - left) / 2.0; const double ray_vertical = (bottom - top ) / 2.0; assert(ray_horizontal > 0.0); assert(ray_vertical > 0.0); const double average_ray = (ray_horizontal + ray_vertical) / 2.0; assert(average_ray > 0.0); const double circumference = average_ray * pi * 2.0; const int n_steps = static_cast<int>(circumference + 0.5); assert(n_steps > 0); const double d_angle = 2.0 * pi / static_cast<double>(n_steps); assert(d_angle > 0.0); double angle = 0.0; for (int i=0; i!=n_steps; ++i) { const double x = midx + (std::sin(angle) * ray_horizontal); const double y = midy - (std::cos(angle) * ray_vertical); DrawDot(x,y); angle += d_angle; } m_signal_changed(this); }
bool FieldView::DrawAllDots(){ bool result(true); //simply accept DrawDot() for every available dot for(int xc = 0; xc < width; xc++) for(int yc = 0; yc < height; yc++) if(!DrawDot(Coordinates(xc, yc))) result = false; return result; }
/* Draws a circle of radius Radius in color Color centered at * screen coordinate (X,Y) */ void DrawCircle(int X, int Y, int Radius, int Color) { int MajorAxis, MinorAxis; unsigned long RadiusSqMinusMajorAxisSq; unsigned long MinorAxisSquaredThreshold; /* Set drawing color via set/reset */ outpw(GC_INDEX, (0x0F << 8) | SET_RESET_ENABLE_INDEX); /* enable set/reset for all planes */ outpw(GC_INDEX, (Color << 8) | SET_RESET_INDEX); /* set set/reset (drawing) color */ outp(GC_INDEX, BIT_MASK_INDEX); /* leave the GC pointing to Bit Mask reg */ /* Set up to draw the circle by setting the initial point to one end of the 1/8th of a circle arc we'll draw */ MajorAxis = 0; MinorAxis = Radius; /* Set initial Radius**2 - MajorAxis**2 (MajorAxis is initially 0 */ RadiusSqMinusMajorAxisSq = (unsigned long) Radius * Radius; /* Set threshold for minor axis movement at (MinorAxis - 0.5)**2 */ MinorAxisSquaredThreshold = (unsigned long) MinorAxis * MinorAxis - MinorAxis; /* Draw all points along an arc of 1/8th of the circle, drawing all 8 symmetries at the same time */ do { /* Draw all 8 symmetries of current point */ DrawDot(X+MajorAxis, Y-MinorAxis); DrawDot(X-MajorAxis, Y-MinorAxis); DrawDot(X+MajorAxis, Y+MinorAxis); DrawDot(X-MajorAxis, Y+MinorAxis); DrawDot(X+MinorAxis, Y-MajorAxis); DrawDot(X-MinorAxis, Y-MajorAxis); DrawDot(X+MinorAxis, Y+MajorAxis); DrawDot(X-MinorAxis, Y+MajorAxis); MajorAxis++; /* advance one pixel along major axis */ if ( (RadiusSqMinusMajorAxisSq -= MajorAxis + MajorAxis - 1) <= MinorAxisSquaredThreshold ) { MinorAxis--; MinorAxisSquaredThreshold -= MinorAxis + MinorAxis; } } while ( MajorAxis <= MinorAxis ); /* Reset the Bit Mask register to normal */ outp(GC_INDEX + 1, 0xFF); /* Turn off set/reset enable */ outpw(GC_INDEX, (0x00 << 8) | SET_RESET_ENABLE_INDEX); }
void ribi::DrawCanvas::DrawCircle(const double xMid, const double yMid, const double ray) noexcept { const double pi = boost::math::constants::pi<double>(); const double circumference = ray * pi * 2.0; const int n_steps = static_cast<int>(circumference + 0.5); if (n_steps == 0) return; assert(n_steps > 0); const double dAngle = 2.0 * pi / static_cast<double>(n_steps); double angle = 0.0; for (int i=0; i!=n_steps; ++i) { double x = xMid + (std::sin(angle) * ray); double y = yMid - (std::cos(angle) * ray); DrawDot(x,y); angle += dAngle; } m_signal_changed(this); }
void ribi::DrawCanvas::DrawLine(const double x1, const double y1, const double x2, const double y2) noexcept { const double dX = x2 - x1; const double dY = y2 - y1; const double dist = std::sqrt( (dX * dX) + (dY * dY) ); const double stepX = dX / dist; const double stepY = dY / dist; const int nSteps = static_cast<int>(dist + 0.5); double x = x1; double y = y1; for (int i=0; i!=nSteps; ++i) { DrawDot(x,y); x+=stepX; y+=stepY; } m_signal_changed(this); }
//------------------------------------------------------------------- //현재 라인의 노드 사이 점 찍기 //------------------------------------------------------------------- Dvoid RenderModule::DrawLine(vector<EdgeNode>& renderLine, const Dint currentHeight, const Dulong dotColor) { Dfloat beginX = -1.0f; Dfloat endX = -1.0f; Dfloat DepthLeft, DepthRight; vector<EdgeNode>::iterator curruntIter; vector<EdgeNode>::iterator nextIter; for( auto iter = begin(renderLine);; ++iter ) { curruntIter = iter; if( curruntIter == end(renderLine) ) break; nextIter = (++iter); if( nextIter == end(renderLine) ) break; beginX = curruntIter->x_min; DepthLeft = GetDepthInterpolation(curruntIter->y_max, curruntIter->y_min, curruntIter->max_depth, curruntIter->min_depth, currentHeight); endX = nextIter->x_min; DepthRight = GetDepthInterpolation(nextIter->y_max, nextIter->y_min, nextIter->max_depth, nextIter->min_depth, currentHeight); curruntIter->x_min += curruntIter->reverseSlope; nextIter->x_min += nextIter->reverseSlope; for( Dint i = (Dint)beginX; i < (Dint)endX; ++i ) { if (i < 0 || i >= m_Width || currentHeight < 0 || currentHeight >= m_Height) { continue; } //좌, 우 사이의 깊이값 보간 Dfloat resultDepth = GetDepthInterpolation(endX, beginX, DepthRight, DepthLeft, i); if (m_pDepthBuffer && m_pDepthBuffer->DepthTest(i, currentHeight, resultDepth)) { DrawDot(i, currentHeight, dotColor); } } } }
void ribi::DrawCanvas::DrawText(const double top, const double left, const std::string& text) noexcept { const int spacing = 2; const boost::shared_ptr<const ribi::DotMatrixString> m { new ribi::DotMatrixString(text,spacing) }; const int width = m->GetMatrixWidth(); const int height = m->GetMatrixHeight(); for (int y=0; y!=height; ++y) { for (int x=0; x!=width; ++x) { if (m->GetMatrix(x,y)) { DrawDot( left + static_cast<double>(x) + 0.5, top + static_cast<double>(y) + 0.5 ); } } } }
/* Draws an ellipse of X axis radius A and Y axis radius B in * color Color centered at screen coordinate (X,Y). Radii must * both be non-zero */ void DrawEllipse(int X, int Y, int A, int B, int Color) { int WorkingX, WorkingY; long Threshold; long ASquared = (long) A * A; long BSquared = (long) B * B; long XAdjust, YAdjust; /* Set drawing color via set/reset */ outpw(GC_INDEX, (0x0F << 8) | SET_RESET_ENABLE_INDEX); /* enable set/reset for all planes */ outpw(GC_INDEX, (Color << 8) | SET_RESET_INDEX); /* set set/reset (drawing) color */ outp(GC_INDEX, BIT_MASK_INDEX); /* leave the GC Index reg pointing to the Bit Mask reg */ /* Draw the four symmetric arcs for which X advances faster (that is, for which X is the major axis) */ /* Draw the initial top & bottom points */ DrawDot(X, Y+B); DrawDot(X, Y-B); /* Draw the four arcs; set draw parameters for initial point (0,B) */ WorkingX = 0; WorkingY = B; XAdjust = 0; YAdjust = ASquared * 2 * B; Threshold = ASquared / 4 - ASquared * B; for (;;) { /* Advance the threshold to the value for the next X point to be drawn */ Threshold += XAdjust + BSquared; /* If the threshold has passed 0, then the Y coordinate has advanced more than halfway to the next pixel and it's time to advance the Y coordinate by 1 and set the next threhold accordingly */ if ( Threshold >= 0 ) { YAdjust -= ASquared * 2; Threshold -= YAdjust; WorkingY--; } /* Advance the X coordinate by 1 */ XAdjust += BSquared * 2; WorkingX++; /* Stop if X is no longer the major axis (the arc has passed the 45-degree point) */ if ( XAdjust >= YAdjust ) break; /* Draw the 4 symmetries of the current point */ DrawDot(X+WorkingX, Y-WorkingY); DrawDot(X-WorkingX, Y-WorkingY); DrawDot(X+WorkingX, Y+WorkingY); DrawDot(X-WorkingX, Y+WorkingY); } /* Draw the four symmetric arcs for which Y advances faster (that is, for which Y is the major axis) */ /* Draw the initial left & right points */ DrawDot(X+A, Y); DrawDot(X-A, Y); /* Draw the four arcs; set draw parameters for initial point (A,0) */ WorkingX = A; WorkingY = 0; XAdjust = BSquared * 2 * A; YAdjust = 0; Threshold = BSquared / 4 - BSquared * A; for (;;) { /* Advance the threshold to the value for the next Y point to be drawn */ Threshold += YAdjust + ASquared; /* If the threshold has passed 0, then the X coordinate has advanced more than halfway to the next pixel and it's time to advance the X coordinate by 1 and set the next threhold accordingly */ if ( Threshold >= 0 ) { XAdjust -= BSquared * 2; Threshold = Threshold - XAdjust; WorkingX--; } /* Advance the Y coordinate by 1 */ YAdjust += ASquared * 2; WorkingY++; /* Stop if Y is no longer the major axis (the arc has passed the 45-degree point) */ if ( YAdjust > XAdjust ) break; /* Draw the 4 symmetries of the current point */ DrawDot(X+WorkingX, Y-WorkingY); DrawDot(X-WorkingX, Y-WorkingY); DrawDot(X+WorkingX, Y+WorkingY); DrawDot(X-WorkingX, Y+WorkingY); } /* Reset the Bit Mask register to normal */ outp(GC_INDEX + 1, 0xFF); /* Turn off set/reset enable */ outpw(GC_INDEX, (0x00 << 8) | SET_RESET_ENABLE_INDEX); }
void DisplayAutoMap(int showAll) { int x, y, i, j; TTile *tile; unsigned char *p; unsigned char *screen; TTileItem *t; int cmd1, cmd2; int obj; screen = p = GetDstScreen(); for (x = 0; x < SCREEN_MEMSIZE; x++) p[x] = tableGreen[p[x] & 0xFF]; screen += MAP_YOFFS * SCREEN_WIDTH + MAP_XOFFS; for (y = 0; y < YMAX; y++) for (i = 0; i < MAP_FACTOR; i++) { for (x = 0; x < XMAX; x++) if (AutoMap(x, y) || showAll) { tile = &Map(x, y); for (j = 0; j < MAP_FACTOR; j++) if ((tile->flags & IS_WALL) != 0) *screen++ = WALL_COLOR; else if ((tile->flags & NO_WALK) != 0) *screen++ = DoorColor(x, y); else *screen++ = FLOOR_COLOR; } else screen += MAP_FACTOR; screen += SCREEN_WIDTH - XMAX * MAP_FACTOR; } for (y = 0; y < YMAX; y++) for (x = 0; x < XMAX; x++) { t = Map(x, y).things; while (t) { if ((t->flags & TILEITEM_OBJECTIVE) != 0) { obj = ObjectiveFromTileItem(t-> flags); if ((gMission.missionData-> objectives[obj]. flags & OBJECTIVE_HIDDEN) == 0 || showAll) { if ((gMission.missionData-> objectives[obj]. flags & OBJECTIVE_POSKNOWN) != 0 || AutoMap(x, y) || showAll) DisplayObjective(t, obj); } } else if (t->kind == KIND_OBJECT && t->data && AutoMap(x, y)) { TObject *o = t->data; if (o->objectIndex == OBJ_KEYCARD_RED) DrawDot(t, RED_DOOR_COLOR); else if (o->objectIndex == OBJ_KEYCARD_BLUE) DrawDot(t, BLUE_DOOR_COLOR); else if (o->objectIndex == OBJ_KEYCARD_GREEN) DrawDot(t, GREEN_DOOR_COLOR); else if (o->objectIndex == OBJ_KEYCARD_YELLOW) DrawDot(t, YELLOW_DOOR_COLOR); } t = t->next; } } DisplayPlayer(gPlayer1); DisplayPlayer(gPlayer2); DisplayExit(); DisplaySummary(); CopyToScreen(); if (!showAll) { do { cmd1 = cmd2 = 0; GetPlayerCmd(gPlayer1 ? &cmd1 : NULL, gPlayer2 ? &cmd2 : NULL); } while (((cmd1 | cmd2) & CMD_BUTTON3) != 0 || KeyDown(gOptions.mapKey)); memset(GetDstScreen(), 0, SCREEN_MEMSIZE); } }
void CRollupGripper::OnPaint() { CPaintDC dc(this); // device context for painting if(m_bInit) { if(MemDC.m_hDC != NULL) { if(pOldMemBMP) { MemDC.SelectObject(pOldMemBMP); #ifdef _DEBUG pOldMemBMP = NULL; #endif } MemDC.DeleteDC(); } MemDC.CreateCompatibleDC((CDC*)&dc); if(MemBMP.m_hObject != NULL) MemBMP.DeleteObject(); MemBMP.CreateCompatibleBitmap((CDC*)&dc, RUP_GRIPPERWIDTH, RUP_GRIPPERHEIGHT); pOldMemBMP = MemDC.SelectObject(&MemBMP); m_bInit = false; } MemDC.FillSolidRect(0,0,RUP_GRIPPERWIDTH,RUP_GRIPPERHEIGHT,GetSysColor(COLOR_BTNFACE)); switch(m_iState) { case GRIPPER_STATE_NORMAL: { // COLORREF hicolor = GetSysColor(COLOR_3DSHADOW); // COLORREF locolor = GetSysColor(COLOR_3DLIGHT); COLORREF hicolor = LightenColor(GetSysColor(COLOR_BTNFACE), -0x50); COLORREF locolor = LightenColor(GetSysColor(COLOR_BTNFACE), 0x10); int yp = 0; for(int yc = 0; yc < GRIPPER_ROWCOUNT; yc++, yp+=5) { int xp = 0; for(int xc = 0; xc < 12; xc++, xp+=5) DrawDot(&MemDC, xp, yp, locolor, hicolor); } break; } case GRIPPER_STATE_MOUSEOVER: { // COLORREF hicolor = GetSysColor(COLOR_3DDKSHADOW); // COLORREF locolor = GetSysColor(COLOR_3DHILIGHT); COLORREF hicolor = LightenColor(GetSysColor(COLOR_BTNFACE), -0x80); COLORREF locolor = LightenColor(GetSysColor(COLOR_BTNFACE), 0x80); int yp = 0; for(int yc = 0; yc < GRIPPER_ROWCOUNT; yc++, yp+=5) { int xp = 0; for(int xc = 0; xc < 12; xc++, xp+=5) DrawDot(&MemDC, xp, yp, locolor, hicolor); } break; } case GRIPPER_STATE_PRESSED: //pressed { COLORREF hicolor = LightenColor(GetSysColor(COLOR_BTNFACE), -0x50); COLORREF locolor = LightenColor(GetSysColor(COLOR_BTNFACE), 0x80); int yp = 0; for(int yc = 0; yc < GRIPPER_ROWCOUNT; yc++, yp+=5) { int xp = 0; for(int xc = 0; xc < 12; xc++, xp+=5) DrawDot(&MemDC, xp, yp, hicolor, locolor); } break; } default: break; } dc.BitBlt(0, 0, RUP_GRIPPERWIDTH, RUP_GRIPPERHEIGHT, &MemDC, 0, 0, SRCCOPY); }
/* Create all the objects, textures, geometry, etc, that we will use */ void InitialiseScene(void) { /* Create new lists, and store its ID number */ gTerrainList = glGenLists(1); gPacman = glGenLists(2); gLQGhost = glGenLists(3); gMQGhost = glGenLists(4); gHQGhost = glGenLists(5); gHQDot = glGenLists(6); gHQFruit = glGenLists(7); // create terrain glNewList(gTerrainList, GL_COMPILE); DrawTerrain(); glEndList(); // create pacman glNewList(gPacman, GL_COMPILE); DrawPacman(); glEndList(); // create ghosts from splines theGhostNurb = gluNewNurbsRenderer(); gluNurbsProperty(theGhostNurb, GLU_SAMPLING_METHOD, GLU_DOMAIN_DISTANCE); gluNurbsProperty(theGhostNurb, GLU_DISPLAY_MODE, GLU_FILL); gluNurbsProperty(theGhostNurb, GLU_CULLING, GL_TRUE); // high quality ghost gluNurbsProperty(theGhostNurb, GLU_U_STEP, 50.); gluNurbsProperty(theGhostNurb, GLU_V_STEP, 50.); glNewList(gHQGhost, GL_COMPILE); DrawGhost(); glEndList(); // medium quality ghost gluNurbsProperty(theGhostNurb, GLU_U_STEP, 20.); gluNurbsProperty(theGhostNurb, GLU_V_STEP, 20.); glNewList(gMQGhost, GL_COMPILE); DrawGhost(); glEndList(); // low quality ghost gluNurbsProperty(theGhostNurb, GLU_U_STEP, 5.); gluNurbsProperty(theGhostNurb, GLU_V_STEP, 5.); glNewList(gLQGhost, GL_COMPILE); DrawGhost(); glEndList(); gluDeleteNurbsRenderer(theGhostNurb); /* create the banana from nurb spline*/ theFruitNurb = gluNewNurbsRenderer(); gluNurbsProperty(theFruitNurb, GLU_SAMPLING_METHOD, GLU_DOMAIN_DISTANCE); gluNurbsProperty(theFruitNurb, GLU_DISPLAY_MODE, GLU_FILL); gluNurbsProperty(theFruitNurb, GLU_CULLING, GL_TRUE); gluNurbsProperty(theFruitNurb, GLU_U_STEP, 20.); gluNurbsProperty(theFruitNurb, GLU_V_STEP, 20.); glNewList(gHQFruit, GL_COMPILE); DrawFruit(); glEndList(); gluDeleteNurbsRenderer(theFruitNurb); /* create a dot */ glNewList(gHQDot, GL_COMPILE); DrawDot(10); glEndList(); }
void GraphView::DrawPoint(int index, wxRegion *region, bool maybe_repaint_cursor) { bool repaint_cursor = false; int current_index = 0; if (index < 0) return; if (!m_draw->GetValuesTable().at(index).IsData()) return; wxDC* dc = m_dc; if (!dc->Ok()) return; int x, y; GetPointPosition(dc, index, &x , &y); bool wide = m_draw->GetSelected() && m_draw->GetDoubleCursor(); int line_width = wide ? 3 : 1; m_sdc.SetLineWidth(wide ? 3 : 1); m_sdc.SetWhiteForeground(); wxPen pen1(m_draw->GetDrawInfo()->GetDrawColor(), line_width, wxSOLID); wxPen pen2(alt_color, line_width, wxSOLID); dc->SetPen(pen1); dc->SetBrush(wxBrush(wxColour(0,0,0), wxTRANSPARENT)); int i = index; const Draw::VT& vt = m_draw->GetValuesTable(); bool is_alternate = AlternateColor(index); if (i - 1 >= 0 && vt.at(i-1).IsData()) { int x1, y1; GetPointPosition(dc, i - 1, &x1, &y1); bool ac = AlternateColor(i - 1); if (ac && is_alternate) { dc->SetPen(pen2); } else { dc->SetPen(pen1); } dc->DrawLine(x1, y1, x, y); m_sdc.DrawLine(x1, y1, x, y); if (ac) dc->SetPen(pen2); else dc->SetPen(pen1); DrawDot(x1, y1, dc, &m_sdc, region); if (region) region->Union(x1 , std::min(y, y1) - line_width, abs(x - x1) + 2 * line_width, abs(y - y1) + 2 * line_width); if (maybe_repaint_cursor && m_draw->GetCurrentIndex() != -1 && m_draw->GetCurrentIndex() == i) { repaint_cursor = true; current_index = i - 1; } } if ((i + 1) < (int)vt.size() && vt.at(i + 1).IsData()) { int x2, y2; bool ac = AlternateColor(i + 1); if (ac && is_alternate) { dc->SetPen(pen2); } else { dc->SetPen(pen1); } GetPointPosition(dc, i + 1, &x2 , &y2); dc->DrawLine(x, y, x2, y2); m_sdc.DrawLine(x, y, x2, y2); if (ac) dc->SetPen(pen2); else dc->SetPen(pen1); DrawDot(x2, y2, dc, &m_sdc, region); if (region) region->Union(x, std::min(y, y2) - line_width, abs(x - x2) + 2 * line_width, abs(y - y2) + 2 * line_width); if (maybe_repaint_cursor && m_draw->GetCurrentIndex() != -1 && m_draw->GetCurrentIndex() == i) { repaint_cursor = true; current_index = i + 1; } } if (is_alternate) dc->SetPen(pen2); else dc->SetPen(pen1); DrawDot(x, y, dc, &m_sdc, region); m_sdc.SetLineWidth(1); pen1.SetWidth(1); pen2.SetWidth(1); if (repaint_cursor) DrawCursor(current_index, region); dc->SetPen(wxNullPen); dc->SetBrush(wxNullBrush); }
cpBool Buoyancy::WaterPreSolve(cpArbiter *arb, cpSpace *space, void *ptr) { CP_ARBITER_GET_SHAPES(arb, water, poly); cpBody *body = cpShapeGetBody(poly); // Get the top of the water sensor bounding box to use as the water level. cpFloat level = cpShapeGetBB(water).t; // Clip the polygon against the water level int count = cpPolyShapeGetCount(poly); int clippedCount = 0; #ifdef _MSC_VER // MSVC is pretty much the only compiler in existence that doesn't support variable sized arrays. cpVect clipped[10]; #else cpVect clipped[count + 1]; #endif for(int i=0, j=count-1; i<count; j=i, i++){ cpVect a = cpBodyLocalToWorld(body, cpPolyShapeGetVert(poly, j)); cpVect b = cpBodyLocalToWorld(body, cpPolyShapeGetVert(poly, i)); if(a.y < level){ clipped[clippedCount] = a; clippedCount++; } cpFloat a_level = a.y - level; cpFloat b_level = b.y - level; if(a_level*b_level < 0.0f){ cpFloat t = cpfabs(a_level)/(cpfabs(a_level) + cpfabs(b_level)); clipped[clippedCount] = cpvlerp(a, b, t); clippedCount++; } } // Calculate buoyancy from the clipped polygon area cpFloat clippedArea = cpAreaForPoly(clippedCount, clipped, 0.0f); cpFloat displacedMass = clippedArea*FLUID_DENSITY; cpVect centroid = cpCentroidForPoly(clippedCount, clipped); cpDataPointer data = ptr; DrawPolygon(clippedCount, clipped, 0.0f, RGBAColor(0, 0, 1, 1), RGBAColor(0, 0, 1, 0.1f), data); DrawDot(5, centroid, RGBAColor(0, 0, 1, 1), data); cpFloat dt = cpSpaceGetCurrentTimeStep(space); cpVect g = cpSpaceGetGravity(space); // Apply the buoyancy force as an impulse. cpBodyApplyImpulseAtWorldPoint(body, cpvmult(g, -displacedMass*dt), centroid); // Apply linear damping for the fluid drag. cpVect v_centroid = cpBodyGetVelocityAtWorldPoint(body, centroid); cpFloat k = k_scalar_body(body, centroid, cpvnormalize(v_centroid)); cpFloat damping = clippedArea*FLUID_DRAG*FLUID_DENSITY; cpFloat v_coef = cpfexp(-damping*dt*k); // linear drag // cpFloat v_coef = 1.0/(1.0 + damping*dt*cpvlength(v_centroid)*k); // quadratic drag cpBodyApplyImpulseAtWorldPoint(body, cpvmult(cpvsub(cpvmult(v_centroid, v_coef), v_centroid), 1.0/k), centroid); // Apply angular damping for the fluid drag. cpVect cog = cpBodyLocalToWorld(body, cpBodyGetCenterOfGravity(body)); cpFloat w_damping = cpMomentForPoly(FLUID_DRAG*FLUID_DENSITY*clippedArea, clippedCount, clipped, cpvneg(cog), 0.0f); cpBodySetAngularVelocity(body, cpBodyGetAngularVelocity(body)*cpfexp(-w_damping*dt/cpBodyGetMoment(body))); return cpTrue; }