"use strict";
var _ = require("lodash"),
COLOR = require("color"),
Condicio = require("condicio"),
Matrix = require("gl-matrix"),
jQuery = require("jquery"),
Node = require("./Node.js"),
DrawingRootNode = require("./DrawingRootNode.js"),
AnimationNode = require("./AnimationNode.js"),
Error = require("../Error.js"),
Utility = require("../Utility.js"),
CvtForJson = require("../CvtForJson.js"),
ParamValidation = require("../ParamValidation.js"),
Style = require("./Style.js");
var NetworkError = Error.NetworkError;
var DataError = Error.DataError;
/**
* @class View3D.NodeFactory
* 三维节点工厂
*
* 提供可创建、加载三维场景中{@link Node}的接口
*
* 应用不应该构建,应该通过{@link View3D}直接获取
*/
function NodeFactory(session, objectID) {
this.objectID = objectID;
this.session = session;
};
/**
* 创建Group节点
*
* @param {Node[]} [nodes] 子节点集合
* @param {String} [name] 节点名称
*
* @return {View3D.Node}
*/
NodeFactory.prototype.createGroup = function (nodes, name) {
name = name || "";
nodes = nodes || [];
ParamValidation.checkIsTypeArray(nodes, Node, "The type of nodes must be 'Node Array' and valid");
Condicio.checkIsString(name, "The type of names must be 'String'!");
var childNodeIDs = CvtForJson.cvtNodeArray(nodes);
var nodeID = Utility.genGUID();
var params = {
nodeID: nodeID,
childNodeIDs: childNodeIDs,
name: name
};
this.session.request(this.objectID, "createGroup", params);
return new Node(this.session, nodeID, name);
};
/**
* 创建MatrixTransform节点
*
* 用于将其子节点进行位置的变换,如平移、旋转等
*
* @param {mat4} mat 位置变换的矩阵表示
* @param {Node[]} [nodes] 子节点的集合,集合中节点不能为空
* @param {String} [name] 创建节点的名称
*
* @return {View3D.Node}
*/
NodeFactory.prototype.createTransformation = function (mat, nodes, name) {
name = name || "";
nodes = nodes || [];
ParamValidation.checkIsMat4(mat, "The type of mat must be 'Matrix-mat4' and valid");
ParamValidation.checkIsTypeArray(nodes, Node, "The type of nodes must be 'Node Array' and valid");
Condicio.checkIsString(name, "The type of name must be 'String'!");
var childNodeIDs = CvtForJson.cvtNodeArray(nodes);;
// 注意:不能直接传递mat给服务端
var matArray = CvtForJson.cvtMat4(mat);
var nodeID = Utility.genGUID();
var params = {
nodeID: nodeID,
mat: matArray,
childNodeIDs: childNodeIDs,
name: name
};
this.session.request(this.objectID, "createTransformation", params);
return new Node(this.session, nodeID, name);
};
/**
* 创建天空盒
*
* @return {View3D.Node}
*/
NodeFactory.prototype.createSkybox = function () {
var nodeID = Utility.genGUID();
this.session.request(this.objectID, "createSkybox", { nodeID:nodeID });
return new Node(this.session, nodeID, "");
};
/**
* 创建用户平面
*
* @param {Number} height 平面高度(毫米)
* @param {String} [name] 平面的名称
*
* @return {View3D.Node}
*/
NodeFactory.prototype.createUserplane = function (height, name) {
name = name || "";
Condicio.checkIsNumber(height, "The type of height must be 'Number'!");
Condicio.checkIsString(name, "The type of name must be 'String'!");
var nodeID = Utility.genGUID();
var params = {
nodeID: nodeID,
name: name,
height: height
};
this.session.request(this.objectID, "createUserplane", params);
return new Node(this.session, nodeID, name);
};
/**
* 加载OGF模型
*
* @param {Object} options 模型加载参数
* @param {String} options.url 模型URL地址 支持“http://”地址和“file:///”格式的下载地址
* @param {Function} options.callback 加载结束回调
* @param {NetworkError/DataError} options.callback.err 加载出错时候返回错误
* err {NetworkError} 模型下载失败
* err {DataError} 模型数据出错
* @param {DrawingRootNode} options.callback.node 加载成功返回加载结果
* @param {Function} [options.progress] 加载进度回调
* @param {Number} options.progress.current 当前加载进度 范围从0到1 0表示加载模型开始 1表示模型加载完成
*/
NodeFactory.prototype.loadOGFModel = function (options) {
Condicio.checkIsObject(options, "The type of options must be 'Object'!");
Condicio.checkIsString(options.url, "The type of url must be 'String'!");
Condicio.checkIsFunction(options.callback, "The type of callback must be 'Function'!");
if (!Condicio.isUndefined(options.progress))
Condicio.checkIsFunction(options.progress, "The type of progress must be 'Function'!");
var _this = this;
var callbackWrapper = function (error, result) {
if (error) {
options.callback(error, null, options.data);
}
else {
//options.callback(null, new DrawingRootNode(_this.session, result.nodeID, result.name));
options.callback(null, new DrawingRootNode(_this.session, result.nodeID, result.name), options.data);
}
if (!Condicio.isUndefined(options.progress))
_this.session.unregisterCallback(progressID);
};
var callbackID = Utility.genGUID();
this.session.registerCallback(callbackID, callbackWrapper, "loadOGFModel");
var params = {
url: options.url,
callbackID: callbackID
};
var progressID = Utility.genGUID();
if (!Condicio.isUndefined(options.progress)) {
params.progressID = progressID;
this.session.registerCallback(progressID, function (error, result) {
options.progress(result.current);
}, "loadOGFModel", true);
}
this.session.request(this.objectID, "loadOGFModel", params);
};
/**
* 加载PGF优化结果
* 需要注意的是这个接口需要配合ROS使用,当与ROS的连接断开时,此接口是不能用的。
*
* @param {Object} options 模型加载参数
* @param {String} options.fileName 模型名字(PGF名字,带后缀,例:uuid.pgf)
* @param {Function} options.callback 加载结束回调
* @param {NetworkError/DataError} options.callback.err 加载出错时候返回错误
* err {NetworkError} 模型下载失败
* err {DataError} 模型数据出错
* @param {DrawingRootNode} options.callback.node 加载成功返回加载结果
* @param {Function} [options.progress] 加载进度回调
* @param {Number} options.progress.current 当前加载进度 范围从0到1 0表示加载模型开始 1表示模型加载完成
*/
NodeFactory.prototype.loadPGFOptimizeResult = function (options) {
Condicio.checkIsObject(options, "The type of options must be 'Object'!");
Condicio.checkIsString(options.fileName, "The type of fileName must be 'String'!");
Condicio.checkIsFunction(options.callback, "The type of callback must be 'Function'!");
if (!Condicio.isUndefined(options.progress))
Condicio.checkIsFunction(options.progress, "The type of progress must be 'Function'!");
var _this = this;
var callbackWrapper = function (error, result) {
if (error) {
options.callback(error, null);
}
else
options.callback(null, new DrawingRootNode(_this.session, result.nodeID, result.name));
if (!Condicio.isUndefined(options.progress))
_this.session.unregisterCallback(progressID);
};
var callbackID = Utility.genGUID();
this.session.registerCallback(callbackID, callbackWrapper, "loadPGFOptimizeResult");
var params = {
fileName: options.fileName,
callbackID: callbackID
};
var progressID = Utility.genGUID();
if (!Condicio.isUndefined(options.progress)) {
params.progressID = progressID;
this.session.registerCallback(progressID, function (error, result) {
options.progress(result.current);
}, "loadPGFOptimizeResult", true);
}
this.session.request(this.objectID, "loadPGFOptimizeResult", params);
};
/**
* 加载PGF模型
*
* @param {Object} options 模型加载参数
* @param {String} options.url 模型URL地址 支持“http://”地址和“file:///”格式的下载地址
* @param {Function} options.callback 加载结束回调
* @param {NetworkError/DataError} options.callback.err 加载出错时候返回错误
* err {NetworkError} 模型下载失败
* err {DataError} 模型数据出错
* @param {DrawingRootNode} options.callback.node 加载成功返回加载结果
* @param {Function} [options.progress] 加载进度回调
* @param {Number} options.progress.current 当前加载进度 范围从0到1 0表示加载模型开始 1表示模型加载完成
*/
NodeFactory.prototype.loadPGFModel = function (options) {
Condicio.checkIsObject(options, "The type of options must be 'Object'!");
Condicio.checkIsString(options.url, "The type of url must be 'String'!");
Condicio.checkIsFunction(options.callback, "The type of callback must be 'Function'!");
if (!Condicio.isUndefined(options.progress))
Condicio.checkIsFunction(options.progress, "The type of progress must be 'Function'!");
var _this = this;
var callbackWrapper = function (error, result) {
if (error) {
options.callback(error, null);
}
else
options.callback(null, new DrawingRootNode(_this.session, result.nodeID, result.name));
if (!Condicio.isUndefined(options.progress))
_this.session.unregisterCallback(progressID);
};
var callbackID = Utility.genGUID();
this.session.registerCallback(callbackID, callbackWrapper, "loadPGFModel");
var params = {
url: options.url,
callbackID: callbackID
};
var progressID = Utility.genGUID();
if (!Condicio.isUndefined(options.progress)) {
params.progressID = progressID;
this.session.registerCallback(progressID, function (error, result) {
options.progress(result.current);
}, "loadPGFModel", true);
}
this.session.request(this.objectID, "loadPGFModel", params);
};
/**
* 创建导航立方体
* <a href="https://wiki.fulongtech.cn/pages/viewpage.action?pageId=108036913">详细请参考</a>
* @param {Object} option 创建导航立方体参数
* @param {vec2} [option.offset = vec2(-90, 80)] 导航立方体的位置参数,第一个值为正(负)表示模型中央与窗口左侧(右侧)的像素偏移量,第二个值为正(负)表示模型中央与窗口上(下)侧的像素偏移量
* @param {double} [option.scale = 150] 自定义导航立方体的大小,默认值为立方体边长为150像素
* @return {View3D.Node}
*/
NodeFactory.prototype.createNavigator = function (option) {
if (Condicio.isUndefined(option)) {
option = {
offset : Matrix.vec2.fromValues(-90, 80),
scale : 150
};
}
if (Condicio.isUndefined(option.offset)) {
option.offset = Matrix.vec2.fromValues(-90, 80)
}
if (Condicio.isUndefined(option.scale)) {
option.scale = 150
}
Condicio.checkIsObject(option, "param option must be a Object");
ParamValidation.checkIsVec2(option.offset, "The type of option-offset must be 'vec2' ");
Condicio.checkIsNumber(option.scale, "The type of opyion-scale must be 'Number'!");
var nodeID = Utility.genGUID();
var posArray = CvtForJson.cvtVec2(option.offset);
var params = {
nodeID: nodeID,
posArray: posArray,
scale: option.scale
};
this.session.request(this.objectID, "createNavigator", params);
return new Node(this.session, nodeID, "");
};
/**
* 释放节点资源
*
* @param {Node[]} nodes 待释放的节点资源集合
*
*/
NodeFactory.prototype.releaseNode = function (nodes) {
ParamValidation.checkIsTypeArray(nodes, Node, "The type of nodes must be 'Node Array' and valid");
var objectIDs = CvtForJson.cvtNodeArray(nodes);
this.session.request(this.objectID, "releaseNode", { objectIDs: objectIDs });
};
/**
* 创建文本批注
*
* @param {Object} option
* @param {String} [option.text = ""] 批注文字,需自带换行(插入'\n')
* @param {vec2[]} [option.pointerPoints] 连线点集合,为空或者未定义,则不能连线,给个点是一个vec2,表示屏幕坐标(单位:像素)
* @param {Object} [option.style] 绘制属性,参照View3D.Style.TextLabelStyle的定义
*
* @return {View3D.Node}
*/
NodeFactory.prototype.createTextLabel = function (option) {
var defaultOption = {
text: "",
pointerPoints:[],
style: Style.TextLabelStyle
};
var newOption = jQuery.extend(true, {}, defaultOption, option);
// 参数检查
Condicio.checkIsObject(newOption, "param option must be a Object");
Condicio.checkIsString(newOption.text, "param text must be a string");
Condicio.checkArgument(newOption.style.fixSizeRange.min >= 0, "param range min must greater than or equal to 0!");
Condicio.checkArgument(newOption.style.fixSizeRange.max > 0, "param range max must greater than 0!");
ParamValidation.checkIsTypeArray(newOption.pointerPoints, Matrix.glMatrix.ARRAY_TYPE, "param pointerPoints must be a 'vec2 Array'");
ParamValidation.checkIsTextLabelStyle(newOption.style);
// 参数与BRS端适配
newOption.style.pointer.line.color = newOption.style.pointer.line.color.rgbaArray();
newOption.style.pointer.identifyLocationPoint.color = newOption.style.pointer.identifyLocationPoint.color.rgbaArray();
newOption.style.textFrame.border.color = newOption.style.textFrame.border.color.rgbaArray();
newOption.style.textFrame.text.color = newOption.style.textFrame.text.color.rgbaArray();
newOption.style.textFrame.text.backdropColor = newOption.style.textFrame.text.backdropColor.rgbaArray();
newOption.style.textFrame.fillColor = newOption.style.textFrame.fillColor.rgbaArray();
var pointerPointsArray = [];
for (var i =0; i<newOption.pointerPoints.length; ++i) {
var pointerPoint = newOption.pointerPoints[i];
pointerPointsArray.push([pointerPoint[0], pointerPoint[1]]);
}
newOption.pointerPoints = pointerPointsArray;
var nodeID = Utility.genGUID();
var params = {
nodeID: nodeID,
option: newOption
};
this.session.request(this.objectID, "createTextLabel", params);
return new Node(this.session, nodeID, "");
};
/**
* 创建图片批注
*
* @param {Object} option 创建图片标签参数
* @param {String} option.pictureUrl 图片地址(支持“http://”地址和“file:///”格式)支持jpg、jpeg、bmp、tga、png图片格式
* @param {Function} option.callback 创建标签结束回调
* @param {NetworkError/DataError} option.callback.err 创建过程出现错误时返回错误
* err {NetworkError} 图片下载失败
* err {DataError} 图片数据出错
* @param {Node} option.callback.node 创建成功返回加载结果
*
*/
NodeFactory.prototype.createPictureLabel = function (option) {
Condicio.checkIsString(option.pictureUrl, "param pictureUrl must be a string");
var _this = this;
var callbackWrapper = function (error, result) {
if (error) {
option.callback(error, null);
}
else
option.callback(null, new Node(_this.session, result.nodeID, result.name));
};
var callbackID = Utility.genGUID();
this.session.registerCallback(callbackID, callbackWrapper, "createPictureLabel");
var params = {
pictureUrl: option.pictureUrl,
callbackID: callbackID
};
this.session.request(this.objectID, "createPictureLabel", params);
};
/**
* 创建线段
*
* @param {vec3} startPt 线段起点
* @param {vec3} endPt 线段终点
* @param {Object} [lineStyle] 线段属性,参照View3D.Style.LineStyle的定义
* @param {String} [name] 节点名称
*
* @return {View3D.Node}
*/
NodeFactory.prototype.createLine = function (startPt, endPt, lineStyle, name) {
var newLineStyle = jQuery.extend({},Style.LineStyle, lineStyle);
name = name || "";
ParamValidation.checkIsVec3(startPt, "The type of startPt must be 'vec3'");
ParamValidation.checkIsVec3(endPt, "The type of endPt must be 'vec3'");
ParamValidation.checkIsLineStyle(newLineStyle);
Condicio.checkIsString(name, "The type of name must be 'String'!");
newLineStyle.color = newLineStyle.color.rgbaArray();
var startPtArray = CvtForJson.cvtVec3(startPt);
var endPtArray = CvtForJson.cvtVec3(endPt);
var nodeID = Utility.genGUID();
var params = {
nodeID: nodeID,
startPoint: startPtArray,
endPoint: endPtArray,
lineStyle: newLineStyle,
nodeName: name
};
this.session.request(this.objectID, "createLine", params);
return new Node(this.session, nodeID, name);
};
/**
* 创建点模型
*
* @param {vec3} point 要绘制的点
* @param {Object} [pointStyle] 点属性,参照View3D.Style.PointStyle的定义
* @param {String} [name] 节点名称
*
* @return {View3D.Node}
*/
NodeFactory.prototype.createPoint = function (point, pointStyle, name) {
name = name || "";
var newPointStyle = jQuery.extend({}, Style.PointStyle, pointStyle);
ParamValidation.checkIsPointStyle(newPointStyle);
ParamValidation.checkIsVec3(point, "The type of point must be 'vec3'");
var numberArray = CvtForJson.cvtVec3(point);
newPointStyle.color = newPointStyle.color.rgbaArray();
var nodeID = Utility.genGUID();
var params = {
nodeID: nodeID,
point: numberArray,
pointStyle: newPointStyle,
nodeName: name
};
this.session.request(this.objectID, "createPoint", params);
return new Node(this.session, nodeID, name);
};
/**
* 创建一个空心球体
* @param {Number} radius 球体半径(单位:毫米)
* @param {COLOR} color 球体颜色(颜色中的alpha值无效)
*
* @return {View3D.Node}
*/
NodeFactory.prototype.createSphere = function(radius, color){
Condicio.checkIsNumber(radius, "The sphere radius must be Number!");
Condicio.checkArgument(radius > 0, "The sphere radius must greater than 0");
//Condicio.checkIsType(color, COLOR, "The type of color must be 'Color'");
var nodeID = Utility.genGUID();
var params = {
nodeID: nodeID,
radius: radius,
color: color.rgbaArray()
};
this.session.request(this.objectID, "createSphere", params);
return new Node(this.session, nodeID, "");
};
/**
* 加载自定义模型
* @param {Object} option 加载自定义模型参数
* @param {String} option.modelUrl 模型文件地址(支持“http://”地址和“file:///”格式),模型文件支持格式:.osg、.ive、.3ds
* @param {Function} option.callback 加载自定义模型结束回调
* @param {NetworkError/DataError} option.callback.err 加载过程出现错误时返回错误
* err {NetworkError} 模型文件下载失败
* err {DataError} 模型数据出错
* @param {Node} option.callback.node 加载成功返回模型节点
*
*/
NodeFactory.prototype.loadModel = function(option){
Condicio.checkIsString(option.modelUrl, "param modelUrl must be a string");
var _this = this;
var callbackWrapper = function (error, result) {
if (error) {
option.callback(error, null);
}
else
option.callback(null, new Node(_this.session, result.nodeID, ""));
};
var callbackID = Utility.genGUID();
this.session.registerCallback(callbackID, callbackWrapper, "loadModel");
var params = {
modelUrl: option.modelUrl,
callbackID: callbackID
};
this.session.request(this.objectID, "loadModel", params);
};
/**
* 加载动画模型
* @param {Object} option 加载动画模型参数
* @param {String} option.modelUrl 模型文件地址(支持“http://”地址和“file:///”格式),模型文件支持格式:.fbx
* @param {Function} option.callback 加载动画模型结束回调
* @param {NetworkError/DataError} option.callback.err 加载过程出现错误时返回错误
* err {NetworkError} 模型文件下载失败
* err {DataError} 模型数据出错
* @param {View3D.AnimationNode} option.callback.node 加载成功返回动画节点
*
*/
NodeFactory.prototype.loadAnimationModel = function(option){
Condicio.checkIsString(option.modelUrl, "param modelUrl must be a string");
var _this = this;
var callbackWrapper = function (error, result) {
if (error) {
option.callback(error, null);
}
else
option.callback(null, new AnimationNode(_this.session, result.nodeID));
};
var callbackID = Utility.genGUID();
this.session.registerCallback(callbackID, callbackWrapper, "loadAnimationModel");
var params = {
modelUrl: option.modelUrl,
callbackID: callbackID
};
this.session.request(this.objectID, "loadAnimationModel", params);
};
/**
* 可配置粒子效果
* <a href="https://fulongtech.atlassian.net/wiki/spaces/RenderingTech/pages/1407025332">参考样例点这里</a>
* <a href="https://fulongtech.atlassian.net/wiki/spaces/~907676428/pages/1326481426">参数具体信息说明</a>
* @param {Object} option 创建粒子
* @param {Function} option.callback 创建粒子效果回调
* @param {Error} option.callback.error 返回错误信息
* err {DataError} 图片文件不存在
* @param {Node} option.callback.node 返回创建的粒子节点
* @param {Object} option.style 粒子参数
* @param {vec3} option.style.direction 发射方向
* @param {vec3} option.style.acceleration 加速度
* @param {Number} option.style.angle 发射角
* @param {Number} option.style.size 单个粒子大小
* @param {Number} option.style.flowRate 流量
* @param {Number} option.style.lifeTime 粒子的存活时间
* @param {String} option.style.imageName 图片文件名
* @param {Object[]} [option.style.alphaInterpolations] 透明度插值
*
*/
NodeFactory.prototype.createParticalSystem = function(option){
ParamValidation.checkIsParticalSystemStyle(option.style);
var direction = CvtForJson.cvtVec3(option.style.direction);
option.style.direction = direction;
var acceleration = CvtForJson.cvtVec3(option.style.acceleration);
option.style.acceleration = acceleration;
var callbackID = Utility.genGUID();
var callbackWrapper = function (error, result) {
if (error) {
option.callback(error, null);
}
else
option.callback(null, new Node(this.session, result.nodeID, ""));
};
this.session.registerCallback(callbackID, callbackWrapper, "createParticalSystem");
var params = {
style: option.style,
callbackID : callbackID,
};
this.session.request(this.objectID, "createParticalSystem", params);
};
/**
* 创建火
* @param {Object} [style] 创建火的参数
* @param {Number} [style.size = 1000] 火的大小
* @param {vec2} [style.direction = vec2(1, 0)] 风向(火、烟的偏移方向)
* @param {Number} [style.angle = 0] 偏移角度(火、烟受风影响而偏移的角度)
*
* @return {View3D.Node}
*/
NodeFactory.prototype.createFire = function(style){
var defaultStyle = {
size : 1000,
direction : Matrix.vec2.fromValues(1, 0),
angle : 0
};
var newStyle = jQuery.extend({}, defaultStyle, style);
ParamValidation.checkIsVec2(newStyle.direction,"The type of style-direction must be 'vec2'" );
Condicio.checkIsNumber(newStyle.size, "The type of style-size must be 'Number'!");
Condicio.checkArgument(newStyle.size > 0, "The size must greater than 0");
Condicio.checkIsNumber(newStyle.angle, "The type of style-angle must be 'Number'!");
var numberArray = CvtForJson.cvtVec2(newStyle.direction);
newStyle.direction = numberArray;
var nodeID = Utility.genGUID();
var params = {
nodeID: nodeID,
style: newStyle
};
this.session.request(this.objectID, "createFire", params);
return new Node(this.session, nodeID, "");
};
/**
* 创建消防喷水
* @param {Object} [style] 喷水参数
* @param {Number} [style.size = 1000] 水柱大小
* @param {vec3} [style.direction = vec3(1, 0, 1)] 喷水方向
*
* @return {View3D.Node}
*/
NodeFactory.prototype.createSprayingWater = function(style){
var defaultStyle = {
size : 1000,
direction : Matrix.vec3.fromValues(1, 0, 1)
};
var newStyle = jQuery.extend({}, defaultStyle, style);
Condicio.checkIsNumber(newStyle.size, "The type of style-size must be 'Number'!");
Condicio.checkArgument(newStyle.size > 0, "The size must greater than 0");
ParamValidation.checkIsVec3(newStyle.direction,"The type of style-direction must be 'vec3'" );
var numberArray = CvtForJson.cvtVec3(newStyle.direction);
newStyle.direction = numberArray;
var nodeID = Utility.genGUID();
var params = {
nodeID: nodeID,
style: newStyle
};
this.session.request(this.objectID, "createSprayingWater", params);
return new Node(this.session, nodeID, "");
};
/**
* 创建多边形
* @param {Object} option 创建多边形参数,支持创建凹凸多边形(创建带纹理的多边形必须要设置贴图url、pixelScale)
* @param {vec3[]} option.points 多边形各个点坐标(点序必须是顺时针或者逆时针)
* @param {COLOR} [option.color = COLOR('rgb(255,255,255)').alpha(1))] 多边形颜色(颜色中的alpha值无效)
* @param {String} [option.url] 多边形贴图地址(支持“http://”地址和“file:///”格式)支持jpg、jpeg、bmp、tga、png图片格式
* @param {Number} [option.pixelScale = 10] 贴图像素点所占比例(贴图的一个像素点占实际图像的边长,eg:输入值为10,标识一个像素点代表实际图像边长10mm)
* @param {Function} option.callback 创建多边形结束回调
* @param {NetworkError/DataError} option.callback.err 加载过程出现错误时返回错误
* err {NetworkError} 贴图文件下载失败
* err {DataError} 贴图数据出错
*
* @param {View3D.Node} option.callback.node 创建成功返回模型节点
*/
NodeFactory.prototype.createPolygon = function(option) {
Condicio.checkIsObject(option, "The type of option must be 'Object'!");
ParamValidation.checkIsTypeArray(option.points, Matrix.glMatrix.ARRAY_TYPE, "The type of points must be 'Number Array' and valid!");
Condicio.checkArgument(option.points.length >= 3, "The points can`t draw polygon! ");
var defaultColor = COLOR('rgb(255,255,255)').alpha(1);
var color = jQuery.extend({}, defaultColor, option.color);
var url = option.url || "";
var pixelScale = option.pixelScale || 10;
var _this = this;
var callbackWrapper = function (error, result) {
if (error) {
option.callback(error, null);
}
else
option.callback(null, new Node(_this.session, result.nodeID, ""));
};
var callbackID = Utility.genGUID();
this.session.registerCallback(callbackID, callbackWrapper, "createPolygon");
var pointArray = [];
for(var i = 0; i < option.points.length; ++i){
var points = CvtForJson.cvtVec3(option.points[i]);
pointArray.push(points);
}
var params = {
points: pointArray,
color: color.rgbaArray(),
url: url,
pixelScale: pixelScale,
callbackID: callbackID
};
this.session.request(this.objectID, "createPolygon", params);
};
/**
* 创建Box
* @param {Object} option 创建Box参数
* @param {vec3[]} option.points Box八个顶点(<a href="https://fulongtech.atlassian.net/wiki/spaces/RenderingTech/pages/83200479">详细请参考</a>)
* @param {COLOR} [option.color = COLOR('rgb(255,255,255)').alpha(1))] Box颜色(颜色中的alpha值无效)
*
* @return {View3D.Node}
*/
NodeFactory.prototype.createBox = function(option) {
ParamValidation.checkIsTypeArray(option.points, Matrix.glMatrix.ARRAY_TYPE, "The type of points must be 'Number Array' and valid!");
Condicio.checkArgument(option.points.length === 8, "The points must be 8 point!");
var pointArray = CvtForJson.cvtVec3Array(option.points);
var defaultColor = COLOR('rgb(255,255,255)').alpha(1);
var color = jQuery.extend({}, defaultColor, option.color);
var nodeID = Utility.genGUID();
var params = {
nodeID: nodeID,
points: pointArray,
color: color.rgbaArray()
};
this.session.request(this.objectID, "createBox", params);
return new Node(this.session, nodeID, "");
};
/**
* 创建扇形旋转体(球体的一部分或者球)
* 先创建出一个xz平面的扇形,然后旋转一定角度得到旋转体
* @param {Object} option 创建扇形旋转体参数
* @param {Number} option.length 扇形边长(毫米)
* @param {Number} option.sectorAngle 扇形角度
* @param {Number} option.rotateAngle 扇形旋转的角度
* @param {vec3} option.direction 扇形旋转体的朝向(圆心到曲面中心点的方向)
* @param {COLOR} [option.color = COLOR('rgb(255,255,255)').alpha(1)] 扇形旋转体颜色(颜色中的alpha值无效)
*
* @return {View3D.Node}
*/
NodeFactory.prototype.createSectorRevolution = function(option) {
Condicio.checkIsNumber(option.sectorAngle, "The type of sectorAngle must be Number! ");
Condicio.checkIsNumber(option.rotateAngle, "The type of rotateAngle must be Number! ");
Condicio.checkIsNumber(option.length,"The type of length must be Number! ");
Condicio.checkArgument(option.length > 0, "The length must greater than '0'! ");
var defaultColor = COLOR('rgb(255,255,255)').alpha(1);
var color = jQuery.extend({}, defaultColor, option.color);
var directionArray = CvtForJson.cvtVec3(option.direction);
var nodeID = Utility.genGUID();
var params = {
nodeID:nodeID,
length:option.length,
sectorAngle:option.sectorAngle,
rotateAngle:option.rotateAngle,
color:color.rgbaArray(),
direction:directionArray
};
this.session.request(this.objectID, "createSectorRevolution", params);
return new Node(this.session, nodeID, "");
};
/**
* 创建圆柱体
* <a href="https://fulongtech.atlassian.net/wiki/spaces/RenderingTech/pages/83200479">详细请参考</a>
* @param {Object} option 创建圆柱参数
* @param {vec3} option.bottomCenter 圆柱体底面中心
* @param {Number} option.bottomRadius 圆柱体底面半径
* @param {vec3} option.bottomNormal 圆柱体底面法向
* @param {vec3} option.topCenter 圆柱体顶面中心
* @param {Number} option.topRadius 圆柱体顶面半径
* @param {vec3} option.topNormal 圆柱体顶面法向
* @param {color} [option.color = COLOR('rgb(255,255,255)').alpha(1)] 圆柱体颜色(颜色中的alpha值无效)
*
* @return {View3D.Node}
*/
NodeFactory.prototype.createCylinder = function(option) {
ParamValidation.checkIsVec3(option.bottomCenter, "The bottomCenter type must be vec3! ");
ParamValidation.checkIsVec3(option.bottomNormal, "The bottomNormal type must be vec3! ");
ParamValidation.checkIsVec3(option.topCenter, "The topCenter type must be vec3! ");
ParamValidation.checkIsVec3(option.topNormal, "The topNormal type must be vec3! ");
Condicio.checkIsNumber(option.bottomRadius, "The bottomRadius type must be Number! ");
Condicio.checkIsNumber(option.topRadius, "The topRadius type must be Number! ");
Condicio.checkArgument(option.bottomRadius >= 0, "bottomRadius must greater than or equal to 0! ");
Condicio.checkArgument(option.topRadius >= 0, "topRadius must greater than or equal to 0! ");
var bottomCenter = CvtForJson.cvtVec3(option.bottomCenter);
var bottomNormal = CvtForJson.cvtVec3(option.bottomNormal);;
var topCenter = CvtForJson.cvtVec3(option.topCenter);;
var topNormal = CvtForJson.cvtVec3(option.topNormal);;
var defaultColor = COLOR('rgb(255,255,255)').alpha(1);
var color = jQuery.extend({}, defaultColor, option.color);
var nodeID = Utility.genGUID();
var params = {
nodeID:nodeID,
bottomCenter:bottomCenter,
bottomRadius:option.bottomRadius,
bottomNormal:bottomNormal,
topCenter:topCenter,
topRadius:option.topRadius,
topNormal:topNormal,
color:color.rgbaArray()
};
this.session.request(this.objectID, "createCylinder", params);
return new Node(this.session, nodeID, "");
};
/**
* 创建圆形断面圆环
* <a href="https://fulongtech.atlassian.net/wiki/spaces/RenderingTech/pages/83200479">详细请参考</a>
* @param {Object} option 创建圆环参数
* @param {vec3} option.pt1 起始圆形断面的中心
* @param {Number} option.radius1 起始圆形断面的半径(>0)
* @param {vec3} option.pt2 截止圆形断面的中心
* @param {Number} option.radius2 截止圆形断面的半径(>0)
* @param {vec3} option.ptCenter 圆环整体中心
* @param {Number} option.direction 圆环的方向
* Direction=0,表示小圆环,从P1到P2的小角度
* Direction=1,表示大圆环,从P1到P2的大角度
* Direction=2,表示整个圆环,此时,P2表示圆环法向量,此时R2无效,以R1为准
* Direction=3,表示半个圆环,此时,P2表示圆环法向量,此时R2无效,以R1为准
* @param {color} [option.color = COLOR('rgb(255,255,255)').alpha(1)] 圆环颜色(颜色中的alpha值无效)
*
* @return {View3D.Node}
*/
NodeFactory.prototype.createTorus = function(option) {
ParamValidation.checkIsVec3(option.pt1, "The option.pt1 type must be vec3! ");
Condicio.checkIsNumber(option.radius1, "The option.radius1 type must be Number! ");
Condicio.checkArgument(option.radius1 > 0, "The option.radius1 type must be greater than 0! ");
ParamValidation.checkIsVec3(option.pt2, "The option.pt2 type must be vec3! ");
var subOut = Matrix.vec3.create();
Condicio.checkArgument(Matrix.vec3.length(Matrix.vec3.sub(subOut, option.pt1, option.pt2)) > 0
, "The option.pt2 must not equal to option.pt1! ");
Condicio.checkIsNumber(option.radius2, "The option.radius2 type must be Number! ");
Condicio.checkArgument(option.radius2 > 0, "The option.radius2 type must be greater than 0! ");
ParamValidation.checkIsVec3(option.ptCenter, "The option.ptCenter type must be vec3! ");
Condicio.checkIsNumber(option.direction, "The option.direction type must be Number! ");
Condicio.checkArgument(option.direction === 0 || option.direction === 1 || option.direction === 2||option.direction === 3
, "The type of option.direction must be valid!");
var pt1 = CvtForJson.cvtVec3(option.pt1);
var pt2 = CvtForJson.cvtVec3(option.pt2);
var ptCenter = CvtForJson.cvtVec3(option.ptCenter);
var defaultColor = COLOR('rgb(255,255,255)').alpha(1);
var color = jQuery.extend({}, defaultColor, option.color);
var nodeID = Utility.genGUID();
var params = {
nodeID:nodeID,
pt1: pt1,
radius1: option.radius1,
pt2: pt2,
radius2: option.radius2,
ptCenter: ptCenter,
direction: option.direction,
color: color.rgbaArray()
};
this.session.request(this.objectID, "createTorus", params);
return new Node(this.session, nodeID, "");
};
/**
* 创建某个根节点(根节点必须是DrawingRootNode)下排除某一部分节点后的其它节点
*
* 返回的node仅用于createColorChangeEffect、createHideEffect、createTransparencyEffect这三种effect中,若用于其他接口中不保证结果;
*
* @param {Node} root 根节点
* @param {Node[]} [excludes] 需要从根节点中排除的一组子节点
*
* @return {View3D.Node}
*/
NodeFactory.prototype.createExclusionNode = function(root, excludes) {
Condicio.checkIsType(root, Node, "The type of root must be 'Node'");
ParamValidation.checkIsTypeArray(excludes, Node, "The type of excludes must be 'Node Array' and valid");
var excludeIDs = CvtForJson.cvtNodeArray(excludes);
var nodeID = Utility.genGUID();
var params = {
nodeID: nodeID,
excludeIDs: excludeIDs,
rootNodeID: root.objectID
};
this.session.request(this.objectID, "createExclusionNode", params);
return new Node(this.session, nodeID, "");
};
/**
* 创建流动效果
* <a href="https://fulongtech.atlassian.net/wiki/spaces/RenderingTech/pages/1504084703">详细请参考</a>
* @param {Object} option 创建流动效果参数
* @param {vec3[]} option.vertexArray 流动的路线,由一组点组成,流经管道的中心点
* @param {Number} option.radius 水流的半径(要比管道半径小一些,推荐管道半径 * 0.8 即可)
* @param {Number} option.speed 流动的速度 单位 m/s
* @param {string} option.textureImageName 纹理图片的name, 放在BRS的Resources文件夹下,支持jpg\png\dds\bmp格式
*
* @param {Function} option.callback 创建节点的回调
* @param {Error} option.callback.err 创建节点的回调参数,内部异常,如果没有异常则为null
* @param {Node} option.callback.node 创建节点的回调参数,返回创建的节点
*
* @param {Function} option.stateCallback 流动状态的回调
* @param {Error} option.stateCallback.err 流动状态回调参数,内部异常,如果没有异常则为null
* @param {vec3} option.stateCallback.pos 流动状态回调参数,当前流到的位置
* @param {boolean} option.stateCallback.flowing 流动状态回调参数,是否正在流动,流动为true,流满为false
*/
NodeFactory.prototype.createFlowingModel = function(option) {
ParamValidation.checkIsVec3Array(option.vertexArray, "The option.vertexArray type must be vec3Array! ");
Condicio.checkArgument(option.vertexArray.length > 1, "The option.vertexArray.size must be greater than 1 ! ");
Condicio.checkIsNumber(option.radius, "The option.radius type must be Number! ");
Condicio.checkArgument(option.radius > 0, "The option.radius must be greater than 0! ");
Condicio.checkIsNumber(option.speed, "The option.speed type must be Number! ");
Condicio.checkArgument(option.speed > 0, "The option.speed must be greater than 0! ");
Condicio.checkIsString(option.textureImageName, "The option.textureImageName type must be String!");
Condicio.checkIsFunction(option.stateCallback, "The type of stateCallback must be 'Function'!");
Condicio.checkIsFunction(option.callback, "The type of callback must be 'Function'!");
var callbackWrapper = function (error, result) {
if (error) {
option.callback(error, null);
}
else {
option.callback(null, new Node(this.session, result.nodeID, ""));
}
};
var callbackID = Utility.genGUID();
this.session.registerCallback(callbackID, callbackWrapper, "createFlowingModel", false);
var stateCallbackID = Utility.genGUID();
this.session.registerCallback(stateCallbackID, option.stateCallback, "createFlowingModel", true);
var nodeID = Utility.genGUID();
var vecs = CvtForJson.cvtVec3Array(option.vertexArray);
var params = {
nodeID : nodeID,
vertexArray : vecs,
radius : option.radius,
speed : option.speed,
textureImageName: option.textureImageName,
callbackID: callbackID,
stateCallbackID: stateCallbackID
};
this.session.request(this.objectID, "createFlowingModel", params);
};
/**
* 创建轴
* @param {Object} option 创建轴的参数
* @param {vec3} option.position 轴的创建位置
* @param {vec3} option.direction 轴的创建方向
* @param {Function} option.pickCallback 创建轴的回调
* @param {Error} option.pickCallback.err 轴点击回调参数,内部异常,如果没有异常则为null
* @param {vec3} option.pickCallback.direction 轴点击回调参数,方向为当前轴所代表的方向
* @param {Object} [option.axisStyle] 轴属性,参照View3D.Style.AxisStyle的定义
*
* @return {View3D.Node}
*/
NodeFactory.prototype.createAxis = function (option) {
var defaultStyle = {
axisStyle: Style.AxisStyle
};
var newOption = jQuery.extend(true,{}, defaultStyle, option);
Condicio.checkIsObject(newOption, "The type of option must be 'Object'!");
ParamValidation.checkIsVec3(newOption.position, "The position type must be vec3! ");
ParamValidation.checkIsVec3(newOption.direction, "The direction type must be vec3! ");
Condicio.checkIsFunction(newOption.pickCallback,"The type of pickCallback must be 'Function'!");
Condicio.checkIsObject(newOption.axisStyle, "The type of axisStyle must be 'Object'!");
ParamValidation.checkIsAxisStyle(newOption.axisStyle);
newOption.axisStyle.color = newOption.axisStyle.color.rgbaArray();
newOption.axisStyle.pickedColor = newOption.axisStyle.pickedColor.rgbaArray();
var style = newOption.axisStyle;
var position = CvtForJson.cvtVec3(newOption.position);
var direction = CvtForJson.cvtVec3(newOption.direction);
var pickCallbackWrapper = function (error, result) {
if (error) {
option.pickCallback(error, null);
}
else{
option.pickCallback(null, CvtForJson.cvtToVec3(result.direction));
}
};
var pickCallbackID = Utility.genGUID();
this.session.registerCallback(pickCallbackID, pickCallbackWrapper, "createAxis", true);
var nodeID = Utility.genGUID();
var params = {
nodeID: nodeID,
position: position,
direction: direction,
callbackID: pickCallbackID,
axisStyle: style,
};
this.session.request(this.objectID, "createAxis", params);
return new Node(this.session, nodeID, "");
};
module.exports = NodeFactory;