PBRT笔记(7)——反射模型

基础术语

表面反射可以分为4大类:

  1. diffuse 漫反射
  2. glossy specular 镜面反射高光
  3. perfect specular 完美反射高光
  4. retro-reflective distributions 后反射分布

几何坐标系以及工具函数

pbrt中的反射是在反射坐标系中进行计算的。坐标系由着色点处法向量与两个切向量组成,也就是
正交基向量(s,t,n),分别于x,y,z相对齐。以\(( \theta ,\phi)\)球体坐标系来表达方向。

从图8.3中可以了解到以下内容,代码在reflection.h中

inline Float CosTheta(const Vector3f &w) { return w.z; }
inline Float Cos2Theta(const Vector3f &w) { return w.z * w.z; }
inline Float AbsCosTheta(const Vector3f &w) { return std::abs(w.z); }
inline Float Sin2Theta(const Vector3f &w) {return std::max((Float)0, (Float)1 - Cos2Theta(w));
}inline Float SinTheta(const Vector3f &w) { return std::sqrt(Sin2Theta(w)); }inline Float TanTheta(const Vector3f &w) { return SinTheta(w) / CosTheta(w); }inline Float Tan2Theta(const Vector3f &w) {return Sin2Theta(w) / Cos2Theta(w);}inline Float CosDPhi(const Vector3f &wa, const Vector3f &wb) {return Clamp((wa.x * wb.x + wa.y * wb.y) /std::sqrt((wa.x * wa.x + wa.y * wa.y) *(wb.x * wb.x + wb.y * wb.y)),-1, 1);
}

基本接口

BRDF与BTDF共享公共基类BxDFBxDFType为反射属性枚举(按照不同的子类修改里面部分枚举的值)

MatchesFlags()用于确定当前BxDF的标签是否与用户提供的一样。

f()返回分布函数值。

完美反射物体例如镜子、玻璃、水之类只能从一个入射方向散射到另一个出射方向,对于这些光线散射情况,就需要特殊处理。这样的BxDF最好是使用delta分布来表示,在此PBRT提供了Sample_f()函数,可以用来处理散射的随机方向采样问题。(使用这个函数氛围使用delta分布与不适用)

virtual Spectrum Sample_f(const Vector3f &wo, Vector3f *wi,const Point2f &sample, Float *pdf,BxDFType *sampledType = nullptr) const;
反射率

半球方向反射率(半球方向上的全反射):
$\rho_{hd}(\omega_o)=\int_{H^2(n)}f_r(p,\omega_o,\omega_i) \left|cos\theta_i \right| d\omega_i $

virtual Spectrum rho(const Vector3f &wo, int nSamples,const Point2f *samples) const;

半球-半球反射率(当前半球方向上所有光线都是一样的情况下,类似兰伯特材质):
$\rho_{hh}=\frac{1}{\pi}\int_{H^2(n)}\int_{H^2(n)}f_r(p,\omega_o,\omega_i) \left|cos\theta_i cos\theta_i \right|d\omega_o d\omega_i $

如果没有提供\(w_o\),计算ρhh,则使用:

virtual Spectrum rho(int nSamples, const Point2f *samples1,const Point2f *samples2) const;

PS.之前看《ray tracing from the ground up》都不知道rho这个函数是啥意思

BxDF缩放适配器

用于取得BxDF的值,并把它缩放至光谱的贡献值。类名为ScaledBxDF

反射高光与透射

在光滑表面(理想状态下)中,反射的出射角与入射角大小相同,遵守菲尼尔定理。一般情况下,计算计算机图形学中的常见操作都会忽略色散现象,以此极大地简化光线传输计算(色散:折射率随着光的波长而变化)。Snell定律:

\(\eta_i sin\theta_i =\eta_t sin \theta_t\)

菲涅尔方程描述了光线接触到表面后反射与透射的比,它实际上Maxwell方程在光滑表面上的求解。
因为在现实环境中光的偏振现象较少,所以在PBRT假设光不偏振。在这个假设下,菲尼尔反射率表示为平行和垂直偏振项的平方的平均值。我们使用\(\eta\)表示折射率

\(r_\parallel=\frac{\eta_t cos\theta_i-\eta_i cos\theta_t}{\eta_t cos\theta_i-\eta_i cos\theta_t}\)

\(r_\bot=\frac{\eta_i cos\theta_i-\eta_t cos\theta_t}{\eta_i cos\theta_i-\eta_t cos\theta_t}\)

对于非偏振光的菲尼尔反射率:

\(F_r=\frac{1}{2}(r_\parallel^2+r_\bot^2)\)

存在几个重要类别需要加以区分:

  1. 第一类是绝缘体(非金属),即不导电的材料。它们有真实的折射率(通常在1-3范围内),并能透射一部分入射光。例如玻璃、矿物油、水和空气。
  2. 第二种是导体(金属),比如金属。导体的导电性会对电磁波中的电子产生一定影响,所以与介质不同,导体的折射率较为复杂:·\(\overline{\eta}=\eta+ik\),k为吸收系数。
  3. 第三种是半导体,本书暂时不考虑。

因为能量守恒的关系,所以绝缘体中透射的能量为1-\(F_r\),FrDielectric函数计算了非偏振光对于绝缘体的菲尼尔反射:

Float FrDielectric(Float cosThetaI, Float etaI, Float etaT) {cosThetaI = Clamp(cosThetaI, -1, 1);//为了计算透射角的cos值,必须确定是在介质内还是外bool entering = cosThetaI > 0.f;if (!entering) {std::swap(etaI, etaT);cosThetaI = std::abs(cosThetaI);}// Snell定律计算cosThetaT Float sinThetaI = std::sqrt(std::max((Float)0, 1 - cosThetaI * cosThetaI));Float sinThetaT = etaI / etaT * sinThetaI;if (sinThetaT >= 1) return 1;Float cosThetaT = std::sqrt(std::max((Float)0, 1 - sinThetaT * sinThetaT));Float Rparl = ((etaT * cosThetaI) - (etaI * cosThetaT)) /((etaT * cosThetaI) + (etaI * cosThetaT));Float Rperp = ((etaI * cosThetaI) - (etaT * cosThetaT)) /((etaI * cosThetaI) + (etaT * cosThetaT));return (Rparl * Rparl + Rperp * Rperp) / 2;
}

导体与绝缘体分界面处的菲尼尔反射率为:
\(r_\bot=\frac{a^2+b^2-2acos\theta+cos^2\theta}{a^2+b^2+2acos\theta+cos^2\theta}\)

\(r_\parallel=r_\bot\frac{cos^2\theta(a^2+b^2)-2acos\theta sin^2\theta +sin^4\theta}{cos^2\theta(a^2+b^2)+2acos\theta sin^2\theta +sin^4\theta}\)

其中:

\(a^2+b^2=\sqrt{(\eta^2-k^2-sin^2\theta)^2+4\eta^2k^2}\)

\(\eta + ik = \overline {\eta_t}/\overline{\eta_i}\)为这个复杂计算后的折射率。但是因为\(\overline{\eta_i}\)是绝缘体的关系,这个部分的计算可以被代替。

Spectrum FrConductor(Float cosThetaI, const Spectrum &etai,const Spectrum &etat, const Spectrum &k) {cosThetaI = Clamp(cosThetaI, -1, 1);Spectrum eta = etat / etai;Spectrum etak = k / etai;Float cosThetaI2 = cosThetaI * cosThetaI;Float sinThetaI2 = 1. - cosThetaI2;Spectrum eta2 = eta * eta;Spectrum etak2 = etak * etak;Spectrum t0 = eta2 - etak2 - sinThetaI2;Spectrum a2plusb2 = Sqrt(t0 * t0 + 4 * eta2 * etak2);Spectrum t1 = a2plusb2 + cosThetaI2;Spectrum a = Sqrt(0.5f * (a2plusb2 + t0));Spectrum t2 = (Float)2 * cosThetaI * a;Spectrum Rs = (t1 - t2) / (t1 + t2);Spectrum t3 = cosThetaI2 * a2plusb2 + sinThetaI2 * sinThetaI2;Spectrum t4 = t2 * sinThetaI2;Spectrum Rp = Rs * (t3 - t4) / (t3 + t4);return 0.5 * (Rp + Rs);
}

为了方便起见,PBRT抽象了一个Fresnel类,并且提供一个Evaluate()方法,用于估算并且返回菲尼尔反射率。在此基础上创建了FresnelConductor、FresnelDielectric、FresnelNoOp类。

FresnelConductor类存储了入射折射率、透射折射率以及吸收系数k。

FresnelDielectric类存储了入射折射率与透射折射。

FresnelNoOp类为菲尼尔反射率为1的情况。在现实生活中不太可能,但为一些操作提供便捷。

反射

SpecularReflection类继承自BxDF类。
其反射公式:

\(L_o(\omega_o)=\int f_r(\omega_o,\omega_i)L_i(\omega_i) \left| cos\theta_i \right| d\omega_i=F_r(\omega_r)L_i(\omega_r)\)

如果使用狄拉克分布来构造这个BRDF,则有:

\(\int f(x)\delta (x-x0)dx=f(x_0)\)

如果希望BRDF在除了完美反射的地方,别的地方皆为0,就建议使用狄拉克分布,则有:

\(f_r(\omega_o,\omega_i)=\delta(\omega_i-\omega_r)F_r(\omega_i)\)

将其带入方程后得:
\(L_o(\omega_o)=\int \delta(\omega_i - \omega_r)F_r(\omega_i)L_i(\omega_i) \left| cos \theta_i\right| d\omega_i=F_r(\omega_r)L_i(\omega_r) \left| cos \theta_r\right|\)

然而它并不正确,因为有了个额外参数\(\theta_r\),将因子分离出来,得到正确结果:

$f_r(p,\omega_o,\omega_i)=F_r(\omega_r)\frac{\delta(\omega_i-\omega_r)}{\left| cos\theta_r\right|} $

因为对于任意方向,delta函数不会返回散射值的原因,所以f()返回0.

然而PBRT确实实现了Sample_f()方法,它根据delta分布选择适当的方向。它将输出变量wi设置为提供的方向wo在表面法线附近的反射。*pdf值设置为1;

Spectrum SpecularReflection::Sample_f(const Vector3f &wo, Vector3f *wi,const Point2f &sample, Float *pdf,BxDFType *sampledType) const {*wi = Vector3f(-wo.x, -wo.y, wo.z);*pdf = 1;return fresnel->Evaluate(CosTheta(*wi)) * R / AbsCosTheta(*wi);
}

如何求反射向量?参看图8.8就明白了。代码:

inline Vector3f Reflect(const Vector3f &wo, const Vector3f &n) {
return -wo + 2 * Dot(wo, n) * n;
}

因为由于在BRDF坐标系系统中,法向量为(0,0,1)所以:*wi = Vector3f(-wo.x, -wo.y, wo.z);

透射

我们使用τ来表示光线透射过介质的能量(别的都被反射了):

\(\tau = 1- Fr(\omega_i).\)

则该介质透射的辐射通量的微分为:

\(d\Phi_o=\tau d\Phi_i\)

使用辐射学的定义代替后:

\(L_ocos\theta_odAd\omega_o=\tau( L_i cos\theta_idAd \omega_i)\)

将平面角度坐标系转换到球面角坐标后:

\(L_ocos\theta_odAsin\theta_od\theta_od\phi_o=\tau( L_i cos\theta_idAsin\theta_id\theta_id\phi_i)\)

将Snell定律进行变换,对于θ有:
\(\eta_ocos\theta_od\theta_o=\eta_icos\theta_id\theta_i=>\frac{cos\theta_od\theta_o}{cos\theta_id\theta_i}=\frac{\eta_i}{\eta_o}\)

将其代入公式8.7中则有:
\(L_o\eta_i^2d\phi_o=\tau L_i\eta_o^2d\phi_i\)

因为\(\phi_i=\phi_o+\pi\)所以\(d\phi_i=d\phi_o\),从而得到:
\(L_o=\tau L_i\frac{\eta_o^2}{\eta_i^2}\)

对于BRDF,我们需要约去一个\(cos\theta_i\)去取得一个正确BTDF用于透射计算。

\(f_r(\omega_o,\omega_i)=\frac{\eta_o^2}{\eta_i^2}(1-F_r(\omega_i))\frac{\delta(\omega_i-T(\omega,n))}{\left| cos\theta_i\right|}\)

其中\(T(\omega_o,n)\)为函数通过法向量与出射角计算出来的透射向量。

因为BTDF是一个缩放后的狄克拉函数,所以f()返回0。

inline bool Refract(const Vector3f &wi, const Normal3f &n, Float eta,Vector3f *wt) {Float cosThetaI = Dot(n, wi);Float sin2ThetaI = std::max(Float(0), Float(1 - cosThetaI * cosThetaI));Float sin2ThetaT = eta * eta * sin2ThetaI;if (sin2ThetaT >= 1) return false;Float cosThetaT = std::sqrt(1 - sin2ThetaT);*wt = eta * -wi + (eta * cosThetaI - cosThetaT) * Vector3f(n);return true;
}Spectrum SpecularTransmission::Sample_f(const Vector3f &wo, Vector3f *wi,const Point2f &sample, Float *pdf,BxDFType *sampledType) const {//确定哪个折射率为透射哪个为入射bool entering = CosTheta(wo) > 0;Float etaI = entering ? etaA : etaB;Float etaT = entering ? etaB : etaA;//计算透射向量if (!Refract(wo, Faceforward(Normal3f(0, 0, 1), wo), etaI / etaT, wi))return 0;*pdf = 1;//透射量计算Spectrum ft = T * (Spectrum(1.) - fresnel.Evaluate(CosTheta(*wi)));//如果是辐射学模式的话再乘以两个介质的折射率平方商if (mode == TransportMode::Radiance) ft *= (etaI * etaI) / (etaT * etaT);return ft / AbsCosTheta(*wi);
}

菲尼尔模式下的反射与透射

为了在蒙特卡洛光线传递算法中(14章~16章会介绍)有更好的效率,我们将会使用一种同时带有折射与反射的BxDF。类名为:FresnelSpecular。具体内容详见代码(会在13~14章介绍具体内容)。

LAMBERTIAN反射

类名为:LambertianReflection。
f()返回 辐射度/π

基于微表面的反射模型

OREN–NAYAR漫反射模型

Oren与Nayar在1994年发现现实世界的物体并没有表现出完美的Lambertian反射具体来说,粗糙的表面通常会随着光照方向接近观察方向而变得更亮。

于是他们开发了一个描述粗糙表面反射模型,基于v形状的微表面,使用球形高斯分布参数与一个变量σ描述。σ为光线与视线的偏差角。

因为假设在V形状微表面的情况下,所以仅需考虑相邻的微表面可以互相反射。这是一个经验近似模型:

\(f_r(\omega_i,\omega_o)=\frac{R}{\pi}(A+B max(0,cos(\phi_i-\phi_o))sin\alpha tan \beta)\)

其中σ为弧度制:

$ A=1-\frac{\sigma^2}{2(\sigma^2+0.33)}$

\(B=\frac{0.45\sigma^2}{\sigma^2+0.09}\)

\(\alpha=max(\theta_i,\theta_o)\)

\(\beta=min(\theta_i,\theta_o)\)

代码参见:OrenNayar::f(const Vector3f &wo, const Vector3f &wi)

微表面分布函数

MicrofacetDistribution为微表面分布的基类。其中一个重要特征就是微表面分布函数D(ωh)。该函数定义于与BxDF相同的BSDF坐标系中。

因此,当ωh等于面法线,且狄克拉函数结果不为0的情况下,完美的光滑表面就可以用狄克拉函数来描述。D(ωh)=δ(ωh−(0,0,1))。

微面分布函数必须normalized,以确保它们在物理上是正确的。直观地说,如果我们考虑沿法线方向n的入射光线,那么每条光线必须与微平面精确相交一次。更正式地说,给定微表面的微分面积dA,那么该面积以上的微面投影面积必须等于dA(参见图8.15)。

\(\int_{H^2(n)}=D(\omega_h)cos\theta_h d\omega_h=1\)

MicrofacetDistribution::D()对应D(ωh)。返回

微表面朝向与法向量对于该区域面积的微分。

Beckmann和Spizzichino(1963)提出了一种基于微面坡度高斯分布的微面分布函数,该函数得到了广泛的应用;实现在BeckmannDistribution类中。Beckmann–Spizzichino模型定义为:

\(D(\omega_h)=\frac{e^{-tan^2\theta_h/\alpha^2}}{\pi\alpha^2cos^4\theta_h}\)

如果σ代表了微表面斜度的平方根,那么α=√2σ

这对定义各项异性非常有用,同时正态分布也取决于ωh的方位取向各不相同。那相对的微表面的各向异性分布函数为:
\(D(\omega_h)=\frac{e^{-tan^2\theta_h(cos^2\phi_h/\alpha_x^2+sin^2\phi_h/\alpha_y^2)}}{\pi\alpha_x\alpha_ycos^4\theta_h}\)

注意,当\(a_x=a_y\)时,该公式将会变成各项同性。

另一种有用的微表面分布函数来自Trowbridge and Reitz (1975).具有各项异性变化:

\(D(\omega_h)=\frac{1}{\pi\alpha_x\alpha_ycos^4\theta_h(1+tan^2\theta_h(cos^2\phi_h/\alpha_x^2+sin^2\phi_h/\alpha_y^2))}\)

与Beckmann–Spizzichino相比,Trowbridge–Reitz精度更高,但是速度更慢。

遮罩与阴影

但是微表面的法线分布还是不够的,还需要考虑到可见性问题。这个效果可以用Smith’s masking-shadowing函数G1(ω, ωh)来表现(注意他的定义域为[0,1])。通常情况下可见性与微表面法线分布式是相互独立的。

\(cos\theta=\int_{H^{2(n)}}G_1(\omega,\omega_h)max(0,\omega \cdot \omega_h)D(\omega_h)d\omega_h\)

换句话说,可见的微表面对于方向ω,必有cosθdA,其中cosθ=(ω · n))

微表面可以看成是一个高度场,每个背光的微表面会遮蔽ω方向上投射面积的向光的微表面。

定义A+为向光面的微表面,A-为背光面的微表面,于是\(cos\theta=A^+(\omega)-A^-(\omega)\)。所以masking-shadowing函数为:

\(G_1(\omega)=\frac{A^+(\omega)-A^-(\omega)}{A^+(\omega)}\)

在每个微表面中不显示区域的比例为:
$ \Lambda{}(\omega)=\frac{A^-(\omega)}{A^+(\omega)-A^-(\omega)}=\frac{A^-(\omega)}{cos\theta}$

我们使用lambda这个函数来计算,同时:
\(G_1(\omega)=\frac{1}{1+\Lambda(\omega)}\)

这个lambda函数可以使用不同的模型来模拟,对于点与点之间没有相关性的模型可以使用Beckmann–Spizzichino:
\(\Lambda(\omega)=\frac{1}{2}(erf(a)-1+\frac{e^{-a^2}}{a\sqrt{\pi}})\)

其中\(a=1/(\alpha tan\theta)\),\(erf(x)=2/\sqrt{\pi}\int_0^x{e^{-x'^2}}dx'\)

PBRT使用了合理的基于物理的多项方程式计算 Beckmann–Spizzichino,这样避免计算了std::erf()与std::exp(),所以计算效率更高。

Masking-shadowing函数的各项异形版本可以通过各向同性版本修改得到。

<Compute alpha for direction w> ≡ 543
Float alpha = std::sqrt(Cos2Phi(w) * alphax * alphax +
Sin2Phi(w) * alphay * alphay);

在高度不相关的前提下,\(\Lambda(\omega)\)对于Trowbridge–Reitz分布可以简化为:
\(\Lambda(\omega)=\frac{-1+\sqrt{1+\alpha^2tan^2\theta}}{2}\)

最后一个有用的是几何属性的微表面分布\(G_1(\omega_o,\omega_i)\),假设从这两个方向观察这个微表面,其可见度的概率是相互独立的,则有
\(G_1(\omega_o,\omega_i)=G_1(\omega_o)G_1(\omega_i)\)

实际上不可能的,因为漏算了当ωo=ωi这个情况。在这个情况下G(ωo, ωi) = G1(ωo) = G1(ωi).这会导致下G(ωo, ωi)过小。同时,当ωo与ωi越接近,其相关性也越大。因此可以推断一个更加精确的微表面模型,假设在微表面上的点越高,其可见度越高。

\(G(\omega_o,\omega_i)=\frac{1}{1+\Lambda(\omega_o)+\Lambda(\omega_i)}\)

这个模型相当精确,PBRT也在使用这个,更为精确的模型请看扩展阅读,当然那个地方我就懒得看了。

Float G(const Vector3f &wo, const Vector3f &wi) const {return 1 / (1 + Lambda(wo) + Lambda(wi));
}

TORRANCE–SPARROW模型

Torrance and Sparrow 于1967年发现了这个微表面模型用于模拟金属表面。这段还是去看知乎上那些介绍实时渲染PBR模型的文章比较好。

$
f(\omega_{o},\omega_{i})=\frac{D(\omega_{h})F(\omega_{o})G(\omega_{o},\omega_{i})}{4 cos\theta_o cos\theta_i}
$

代码在MicrofacetReflection中的f()中。MicrofacetTransmission则实现了透射效果。入射介质折射率、透射介质折射率以及\(d\omega_h d\omega_o\)的关系如下:

\(d\omega_h=\frac{\eta_o^2 \left | \omega_o \cdot \omega_h\right|d\omega_o}{(\eta_i(\omega_i \cdot \omega_h)+\eta_o(\omega_o \cdot \omega_h))^2}\)

代入之前的公式:

\(f_r(\omega_o,\omega_i)=\frac{\eta^2D(\omega_h)G(\omega_o,\omega_i)(1-F_r(\omega_o))}{((\omega_o \cdot \omega_h)+\eta(\omega_i \cdot \omega_h))^2}\frac{\left| \omega_i \cdot \omega_h\right| \left|\omega_o \cdot \omega_h \right|}{cos\theta_o cos\theta_i}\)

其中\(\omega_h=\omega_o+\eta \omega_i\)

多层材质模型

很多BRDF模型都没有考虑到在多层材质中,最底层的材质对于光线的影响。Ashikhmin和Shirley(2000, 2002)开发了模拟这种表面是粗糙的漫反射,底面为光滑的镜面反射的多层材质的BRDF模型。图8.23显示了这个想法:当入射方向接近垂直时,大部分光被传输到漫反射表层,漫反射占主导地位。当入射方向接近掠射时,底层的镜面反射占主导地位。车漆就适合用这种模型来表现。类名为FresnelBlend。

FresnelBlend类设置了两个辐射度变量分别来控制漫反射与镜面反射,以及一个微表面分布变量来控制高光层。

这个模型基于镜面反射层与漫反射层的权重和。再考虑了能量守恒的情况下,其镜面高光部分为:
\(f_r(p,\omega_o,\omega_i)=\frac{D(\omega_h)F(\omega_o)}{4(\omega_h \cdot \omega_i)(max((n \cdot \omega_o),(n \cdot \omega_i))}\)

下面使用了Schlick菲尼尔近似模型。其漫反射部分为:
\(f_r(p,\omega_i,\omega_o)=\frac{28R_d}{23\pi}(1-R_s)(1-(1-\frac{(n\cdot \omega_i)}{2})^5)(1-(1-\frac{(n \cdot \omega_o)}{2})^5)\)

最终返回镜面高光+漫反射的值。

转载于:https://www.cnblogs.com/blueroses/p/10159211.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/449919.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux grep命令、Linux cd命令、Linux pwd命令

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Linux grep命令用于查找文件里符合条件的字符串。 grep指令用于查找内容包含指定的范本样式的文件&#xff0c;如果发现某文件的内容符…

忠告:创业公司与大公司正面竞争易死

移动互联网的兴起给了创业公司足够的发展空间&#xff0c;也提供了一个相对公平的竞争平台。但机遇永远与挑战并存。   对于初创公司&#xff0c;最大的挑战莫过于在移动互联网大潮中生存下来。IDG资本合伙人高翔认为&#xff0c;初创公司不要和大公司正面竞争&#xff0c;应…

海康萤石摄像机远程监控机制分析

背景介绍 有一个远程监控的需求&#xff0c;正常情况下采用服务器转发视频流对服务器要求很高&#xff0c;所以p2p看似是一个比较好的方案&#xff0c;但是p2p打洞却不是一件容易的事情&#xff0c;所以打算分析下海康萤石摄像机远程监控的机制&#xff0c;是否采用了p2p的方式…

实体类中存在List集合,怎么在xml文件中,对应

public class AppointmentDTO {/**订单id**/private String appointmentId;/**订单里面的商品list**/private List<CommodityShowInAppoinment> list;/**订单里面的商品数量**/private Integer count;/**订单实际付款的金额**/private Float totalMoney; } 怎么弄呢&…

git管理复杂项目代码

背景 我初学前端的时候接触git&#xff0c;那时候只要会add/commit什么的就好了&#xff0c;网上的教程大多都停留在从头到尾一个个介绍git的命令&#xff0c;关于各种用法&#xff0c;特别是多个分支来回交叉冲突的实际处理&#xff0c;很少有这方面的介绍&#xff0c;经过很多…

实现一个通用的生产者消费者队列(c语言版本)

背景&#xff1a;笔者之前一直从事嵌入式音视频相关的开发工作&#xff0c;对于音视频的数据的处理&#xff0c;生产者消费者队列必不可少&#xff0c;而如何实现一个高效稳定的生产者消费者队列则十分重要&#xff0c;不过按照笔者从业的经验&#xff0c;所看到的现象&#xf…

美媒:小米新浪达成合作 采取行动对抗腾讯

来自美媒的报道称&#xff0c;两家中国最具发展潜力的科技公司&#xff0c;新浪和小米将会共同合作&#xff0c;结合各自的通信应用程序来共同对抗移动通信的挑战&#xff0c;尤其是拥有2亿用户的强劲对手微信。 来自中国的消息称&#xff0c;这次新浪与小米的合作将会涉及到新…

Linux expr命令、Linux wc命令、Linux let 命令

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 expr命令是一个手工命令行计数器&#xff0c;用于在UNIX/LINUX下求表达式变量的值&#xff0c;一般用于整数值&#xff0c;也可用于字符…

【English】六、am,is,are 分别用在什么地方

is&#xff1a;第三人称单数am&#xff1a;第一人称单数are&#xff1a;第二人称单数&#xff0c;第一、二、三人称的复数 用于第一人称, I am ......(我是.......)用于第三人称, He is ......(他是......) 或She is ......(她是......), It is ......(它是.......)用于第二人…

误删了公司数据库,但我还是活下来了

专栏 | 九章算法 网址 | www.jiuzhang.com 上周我与同事们进行了一次关于职业生涯中搞砸了一些事情的简短谈话。这确实会沦为他人笑柄&#xff0c;却更给我们带来了珍贵的教训。重要的是&#xff0c;我们应该分享那些曾经的错误&#xff0c;这样其他人就可以从其中学习。下文是…

改良程序的11技巧

有很多理由都能说明为什么我们应该写出清晰、可读性好的程序。最重要的一点&#xff0c;程序你只写一次&#xff0c;但以后会无数次的阅读。当你第二天回头来看你的代码时&#xff0c;你就要开始阅读它了。当你把代码拿给其他人看时&#xff0c;他必须阅读你的代码。因此&#…

历时四年,给Google提交的Android Framework Bug终于被Fixed了

历时四年&#xff0c;Google终于修复了一个我发现的Android Framework Bug 2014年在做一个Android终端设备开发过程中&#xff0c;发现了一个Android Framework层的Bug&#xff0c;给Google提交了issue和解决方案&#xff0c;和外界传言一致Google一般不太在意个人开发者提交的…

Linux ping命令、Linux kill命令、Linux logname命令、 Linux logout命令

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Linux ping命令用于检测主机。 执行ping指令会使用ICMP传输协议&#xff0c;发出要求回应的信息&#xff0c;若远端主机的网络功能没有…

前端布局神器display:flex

2009年&#xff0c;W3C提出了一种新的方案--Flex布局&#xff0c;可以简便、完整、响应式地实现各种页面布局。目前已得到所有现在浏览器的支持。 flex浏览器支持一、Flex布局是什么&#xff1f; Flex是Flexible Box的缩写&#xff0c;翻译成中文就是“弹性盒子”&#xff0c;用…

bind简单转发实验

2019独角兽企业重金招聘Python工程师标准>>> *主配置文件内容// [rootlocalhost /]# cat /etc/named.conf // // named.conf // // Provided by Red Hat bind package to configure the ISC BIND named(8) DNS // server as a caching only nameserver (as a local…

数据结构:块状链表

一、概述 有时候我们需要设计这样一种数据结构&#xff1a;它能快速在要求位置插入或者删除一段数据。先考虑两种简单的数据结构&#xff1a;数组和链表。数组的优点是能够在O(1)的时间内找到所要执行操作的位置&#xff0c;但其缺点是无论是插入或删除都要移动之后的所有数据&…

记账本开发小计(四)

今天处理的是记账本小软件中的查询功能&#xff0c;由于账目的要求就是准确性&#xff0c;所以对于记账本程序来说&#xff0c;模糊查询并不适用&#xff0c;所以在这里只能是按照指定的条件来进行查询所以我做的事按照时间进行查询&#xff0c;为了方便进行处理&#xff0c;这…

Linux ps命令、Linux top命令

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Linux ps命令用于显示当前进程 (process) 的状态。 语法 ps [options] [--help][options] [--help] 参数&#xff1a; ps 的参数非常…

Prime Distance POJ - 2689 线性筛

一个数 $n$ 必有一个不超过 $\sqrt n$ 的质因子。 打表处理出 $1$ 到 $\sqrt n$ 的质因子后去筛掉属于 $L$ 到 $R$ 区间的素数即可。 Code: #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; const…

给定a和n,计算a+aa+aaa+a...a(n个a)的和(大数据处理)

题目描述&#xff1a;给定a和n&#xff0c;计算aaaaaaa...a(n个a)的和。 输入&#xff1a;测试数据有多组&#xff0c;输入a&#xff0c;n&#xff08;1<a<9,1<n<100&#xff09;。 输出&#xff1a;对于每组输入,请输出结果。 样例输入&#xff1a;1 10 样例输出&…