void rspfImageViewAffineTransform::buildCompositeTransform() { NEWMAT::Matrix scaleM(3, 3); NEWMAT::Matrix rotzM = rspfMatrix3x3::createRotationZMatrix(m_rotation); NEWMAT::Matrix transM(3,3); NEWMAT::Matrix transOriginM(3,3); NEWMAT::Matrix transOriginNegatedM(3,3); transM << 1 << 0 << m_translate.x << 0 << 1 << m_translate.y << 0 << 0 << 1; transOriginM << 1 << 0 << m_pivot.x << 0 << 1 << m_pivot.y << 0 << 0 << 1; transOriginNegatedM << 1 << 0 << -m_pivot.x << 0 << 1 << -m_pivot.y << 0 << 0 << 1; scaleM << m_scale.x << 0 << 0 << 0 << m_scale.y << 0 << 0 << 0 << 1; m_transform = transM*scaleM*transOriginM*rotzM*transOriginNegatedM; m_inverseTransform = m_transform.i(); }
math::Matrix<float, 4, 4> Arrow3d::CalculateTransform(ScreenBase const & screen, float dz) const { double arrowScale = VisualParams::Instance().GetVisualScale() * kArrowSize; if (screen.isPerspective()) { static double const kLog2 = log(2.0); double const kMaxZoom = scales::UPPER_STYLE_SCALE + 1.0; double const zoomLevel = my::clamp(fabs(log(screen.GetScale()) / kLog2), kArrow3dMinZoom, kMaxZoom); double const t = (zoomLevel - kArrow3dMinZoom) / (kMaxZoom - kArrow3dMinZoom); arrowScale *= (kArrow3dScaleMin * (1.0 - t) + kArrow3dScaleMax * t); } double const scaleX = arrowScale * 2.0 / screen.PixelRect().SizeX(); double const scaleY = arrowScale * 2.0 / screen.PixelRect().SizeY(); double const scaleZ = screen.isPerspective() ? (0.002 * screen.GetDepth3d()) : 1.0; m2::PointD const pos = screen.GtoP(m_position); double const dX = 2.0 * pos.x / screen.PixelRect().SizeX() - 1.0; double const dY = 2.0 * pos.y / screen.PixelRect().SizeY() - 1.0; math::Matrix<float, 4, 4> scaleM = math::Identity<float, 4>(); scaleM(0, 0) = scaleX; scaleM(1, 1) = scaleY; scaleM(2, 2) = scaleZ; math::Matrix<float, 4, 4> rotateM = math::Identity<float, 4>(); rotateM(0, 0) = cos(m_azimuth + screen.GetAngle()); rotateM(0, 1) = -sin(m_azimuth + screen.GetAngle()); rotateM(1, 0) = -rotateM(0, 1); rotateM(1, 1) = rotateM(0, 0); math::Matrix<float, 4, 4> translateM = math::Identity<float, 4>(); translateM(3, 0) = dX; translateM(3, 1) = -dY; translateM(3, 2) = dz; math::Matrix<float, 4, 4> modelTransform = rotateM * scaleM * translateM; if (screen.isPerspective()) return modelTransform * math::Matrix<float, 4, 4>(screen.Pto3dMatrix()); return modelTransform; }
/*- render_particles から呼ばれる。粒子の数だけ繰り返し -*/ void Particles_Engine::do_render( TFlash *flash, Particle *part, TTile *tile, std::vector<TRasterFxPort *> part_ports, std::map<int, TTile *> porttiles, const TRenderSettings &ri, TDimension &p_size, TPointD &p_offset, int lastframe, std::vector<TLevelP> partLevel, struct particles_values &values, double opacity_range, int dist_frame, std::map<std::pair<int, int>, double> &partScales) { // Retrieve the particle frame - that is, the *column frame* from which we are // picking // the particle to be rendered. int ndx = part->frame % lastframe; TRasterP tileRas(tile->getRaster()); std::string levelid; double aim_angle = 0; if (values.pathaim_val) { double arctan = atan2(part->vy, part->vx); aim_angle = arctan * M_180_PI; } // Calculate the rotational and scale components we have to apply on the // particle TRotation rotM(part->angle + aim_angle); TScale scaleM(part->scale); TAffine M(rotM * scaleM); // Particles deal with dpi affines on their own TAffine scaleAff(m_parent->handledAffine(ri, m_frame)); double partScale = scaleAff.a11 * partScales[std::pair<int, int>(part->level, ndx)]; TDimensionD partResolution(0, 0); TRenderSettings riNew(ri); // Retrieve the bounding box in the standard reference TRectD bbox(-5.0, -5.0, 5.0, 5.0), standardRefBBox; if (part->level < (int)part_ports.size() && // Not the default levelless cases part_ports[part->level]->isConnected()) { TRenderSettings riIdentity(ri); riIdentity.m_affine = TAffine(); (*part_ports[part->level])->getBBox(ndx, bbox, riIdentity); // A particle's bbox MUST be finite. Gradients and such which have an // infinite bbox // are just NOT rendered. // NOTE: No fx returns half-planes or similar (ie if any coordinate is // either // (std::numeric_limits<double>::max)() or its opposite, then the rect IS // THE infiniteRectD) if (bbox == TConsts::infiniteRectD) return; } // Now, these are the particle rendering specifications bbox = bbox.enlarge(3); standardRefBBox = bbox; riNew.m_affine = TScale(partScale); bbox = riNew.m_affine * bbox; /*- 縮小済みのParticleのサイズ -*/ partResolution = TDimensionD(tceil(bbox.getLx()), tceil(bbox.getLy())); if (flash) { if (!partLevel[part->level]->frame(ndx)) { if (part_ports[0]->isConnected()) { TTile auxTile; TRaster32P tmp; tmp = TRaster32P(p_size); (*part_ports[0]) ->allocateAndCompute(auxTile, p_offset, p_size, tmp, ndx, ri); partLevel[part->level]->setFrame(ndx, TRasterImageP(auxTile.getRaster())); } } flash->pushMatrix(); const TAffine aff; flash->multMatrix(scaleM * aff.place(0, 0, part->x, part->y)); // if(curr_opacity!=1.0 || part->gencol.fadecol || part->fincol.fadecol || // part->foutcol.fadecol) { TColorFader cf(TPixel32::Red, .5); flash->draw(partLevel[part->level]->frame(ndx), &cf); } // flash->draw(partLevel->frame(ndx), 0); flash->popMatrix(); } else { TRasterP ras; std::string alias; TRasterImageP rimg; if (rimg = partLevel[part->level]->frame(ndx)) { ras = rimg->getRaster(); } else { alias = "PART: " + (*part_ports[part->level])->getAlias(ndx, riNew); if (rimg = TImageCache::instance()->get(alias, false)) { ras = rimg->getRaster(); // Check that the raster resolution is sufficient for our purposes if (ras->getLx() < partResolution.lx || ras->getLy() < partResolution.ly) ras = 0; else partResolution = TDimensionD(ras->getLx(), ras->getLy()); } } // We are interested in making the relation between scale and (integer) // resolution // bijective - since we shall cache by using resolution as a partial // identification parameter. // Therefore, we find the current bbox Lx and take a unique scale out of it. partScale = partResolution.lx / standardRefBBox.getLx(); riNew.m_affine = TScale(partScale); bbox = riNew.m_affine * standardRefBBox; // If no image was retrieved from the cache (or it was not scaled enough), // calculate it if (!ras) { TTile auxTile; (*part_ports[part->level]) ->allocateAndCompute(auxTile, bbox.getP00(), TDimension(partResolution.lx, partResolution.ly), tile->getRaster(), ndx, riNew); ras = auxTile.getRaster(); // For now, we'll just use 32 bit particles TRaster32P rcachepart; rcachepart = ras; if (!rcachepart) { rcachepart = TRaster32P(ras->getSize()); TRop::convert(rcachepart, ras); } ras = rcachepart; // Finally, cache the particle addRenderCache(alias, TRasterImageP(ras)); } if (!ras) return; // At this point, it should never happen anyway... // Deal with particle colors/opacity TRaster32P rfinalpart; double curr_opacity = part->set_Opacity(porttiles, values, opacity_range, dist_frame); if (curr_opacity != 1.0 || part->gencol.fadecol || part->fincol.fadecol || part->foutcol.fadecol) { /*- 毎フレーム現在位置のピクセル色を参照 -*/ if (values.pick_color_for_every_frame_val && values.gencol_ctrl_val && (porttiles.find(values.gencol_ctrl_val) != porttiles.end())) part->get_image_reference(porttiles[values.gencol_ctrl_val], values, part->gencol.col); rfinalpart = ras->clone(); part->modify_colors_and_opacity(values, curr_opacity, dist_frame, rfinalpart); } else rfinalpart = ras; // Now, let's build the particle transform before it is overed on the output // tile // First, complete the transform by adding the rotational and scale // components from // Particles parameters M = ri.m_affine * M * TScale(1.0 / partScale); // Then, retrieve the particle position in current reference. TPointD pos(part->x, part->y); pos = ri.m_affine * pos; // Finally, add the translational component to the particle // NOTE: p_offset is added to account for the particle relative position // inside its level's bbox M = TTranslation(pos - tile->m_pos) * M * TTranslation(bbox.getP00()); if (TRaster32P myras32 = tile->getRaster()) TRop::over(tileRas, rfinalpart, M); else if (TRaster64P myras64 = tile->getRaster()) TRop::over(tileRas, rfinalpart, M); else throw TException("ParticlesFx: unsupported Pixel Type"); } }
void Arrow3d::Render(ScreenBase const & screen, ref_ptr<dp::GpuProgramManager> mng) { // Unbind current VAO, because glVertexAttributePointer and glEnableVertexAttribute can affect it. GLFunctions::glBindVertexArray(0); ref_ptr<dp::GpuProgram> prg = mng->GetProgram(gpu::ARROW_3D_PROGRAM); prg->Bind(); if (!m_isInitialized) { Build(prg); m_isInitialized = true; } dp::ApplyState(m_state, prg); static double const kLog2 = log(2.0); double const kMaxZoom = scales::UPPER_STYLE_SCALE + 1.0; double const zoomLevel = my::clamp(fabs(log(screen.GetScale()) / kLog2), kArrow3dMinZoom, kMaxZoom); double const t = (zoomLevel - kArrow3dMinZoom) / (kMaxZoom - kArrow3dMinZoom); double const arrowScale = kArrow3dScaleMin * (1.0 - t) + kArrow3dScaleMax * t; double const scaleX = m_pixelWidth * arrowScale * 2.0 / screen.PixelRect().SizeX() / kArrowSizeX; double const scaleY = m_pixelHeight * arrowScale * 2.0 / screen.PixelRect().SizeY() / kArrowSizeY; double const scaleZ = scaleX; m2::PointD const pos = screen.GtoP(m_position); double const dX = 2.0 * pos.x / screen.PixelRect().SizeX() - 1.0; double const dY = 2.0 * pos.y / screen.PixelRect().SizeY() - 1.0; math::Matrix<float, 4, 4> scaleM = math::Identity<float, 4>(); scaleM(0, 0) = scaleX; scaleM(1, 1) = scaleY; scaleM(2, 2) = scaleZ; math::Matrix<float, 4, 4> rotateM = math::Identity<float, 4>(); rotateM(0, 0) = cos(m_azimuth + screen.GetAngle()); rotateM(0, 1) = -sin(m_azimuth + screen.GetAngle()); rotateM(1, 0) = -rotateM(0, 1); rotateM(1, 1) = rotateM(0, 0); math::Matrix<float, 4, 4> translateM = math::Identity<float, 4>(); translateM(3, 0) = dX; translateM(3, 1) = -dY; math::Matrix<float, 4, 4> modelTransform = rotateM * scaleM * translateM; modelTransform = modelTransform * math::Matrix<float, 4, 4>(screen.Pto3dMatrix()); dp::UniformValuesStorage uniforms; uniforms.SetMatrix4x4Value("m_transform", modelTransform.m_data); dp::ApplyUniforms(uniforms, prg); GLFunctions::glBindBuffer(m_bufferId, gl_const::GLArrayBuffer); GLFunctions::glEnableVertexAttribute(m_attributePosition); GLFunctions::glVertexAttributePointer(m_attributePosition, 3, gl_const::GLFloatType, false, 0, 0); GLFunctions::glBindBuffer(m_bufferNormalsId, gl_const::GLArrayBuffer); GLFunctions::glEnableVertexAttribute(m_attributeNormal); GLFunctions::glVertexAttributePointer(m_attributeNormal, 3, gl_const::GLFloatType, false, 0, 0); GLFunctions::glDrawArrays(gl_const::GLTriangles, 0, m_vertices.size() / 3); prg->Unbind(); GLFunctions::glBindBuffer(0, gl_const::GLArrayBuffer); }